From 4067eb9c5dd919bcb151c0219ba27080a2f23412 Mon Sep 17 00:00:00 2001 From: Duy Anh Philippe PHAM Date: Wed, 11 Mar 2026 16:19:06 +0100 Subject: [PATCH 1/4] Add Replace Special Values Feature * [ADD] : datalab/widgets/replacespecialvalues.py : - add custom dialog for Replace special values - show NaN / +Inf / -Inf counters - add neighbor mask preview for signal and image strategies - provide DataLab-specific parameter classes for signal and image * [UPDATE] : datalab/gui/processor/signal.py and datalab/gui/processor/image.py : - register replace_special_values processing - use dedicated DataLab parameter dialog classes * [UPDATE] : datalab/gui/actionhandler.py : - add Replace special values in Level adjustment menu * [ADD] : datalab/data/icons/processing/replace_nan.svg : - add icon for Replace special values action * [FIX] : datalab/adapters_plotpy/objects/signal.py : - avoid passing dx/dy to plain CurveItem when no real error bars are available - keep ErrorBarCurveItem handling unchanged --- datalab/adapters_plotpy/objects/signal.py | 9 +- datalab/data/icons/processing/replace_nan.svg | 12 + datalab/gui/actionhandler.py | 1 + datalab/gui/processor/image.py | 9 + datalab/gui/processor/signal.py | 9 + datalab/widgets/replacespecialvalues.py | 408 ++++++++++++++++++ 6 files changed, 446 insertions(+), 2 deletions(-) create mode 100644 datalab/data/icons/processing/replace_nan.svg create mode 100644 datalab/widgets/replacespecialvalues.py diff --git a/datalab/adapters_plotpy/objects/signal.py b/datalab/adapters_plotpy/objects/signal.py index 2a2dd937..69a1e3de 100644 --- a/datalab/adapters_plotpy/objects/signal.py +++ b/datalab/adapters_plotpy/objects/signal.py @@ -15,7 +15,7 @@ import numpy as np from guidata.dataset import restore_dataset, update_dataset from plotpy.builder import make -from plotpy.items import CurveItem +from plotpy.items import CurveItem, ErrorBarCurveItem from sigima.objects import SignalObj from datalab.adapters_plotpy.objects.base import ( @@ -245,7 +245,12 @@ def update_item(self, item: CurveItem, data_changed: bool = True) -> None: and isinstance(dx, np.ndarray) and isinstance(dy, np.ndarray) ) - item.set_data(x.real, y.real, dx.real, dy.real) + if isinstance(item, ErrorBarCurveItem): + item.set_data(x.real, y.real, dx.real, dy.real) + else: + # xydata has 4 rows but dx/dy are all NaN (no real + # error bars) — the plot item is a plain CurveItem + item.set_data(x.real, y.real) item.param.label = o.title apply_downsampling(item) # Reapply linewidth with smart clamping (data size may have changed) diff --git a/datalab/data/icons/processing/replace_nan.svg b/datalab/data/icons/processing/replace_nan.svg new file mode 100644 index 00000000..dea21bb3 --- /dev/null +++ b/datalab/data/icons/processing/replace_nan.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/datalab/gui/actionhandler.py b/datalab/gui/actionhandler.py index 22e4803e..1322d074 100644 --- a/datalab/gui/actionhandler.py +++ b/datalab/gui/actionhandler.py @@ -1050,6 +1050,7 @@ def create_first_actions(self): with self.new_menu(_("Level adjustment"), icon_name="level_adjustment.svg"): self.action_for("normalize") self.action_for("clip") + self.action_for("replace_special_values") self.new_action( _("Offset correction"), triggered=self.panel.processor.compute_offset_correction, diff --git a/datalab/gui/processor/image.py b/datalab/gui/processor/image.py index 5f0c5b75..20d36330 100644 --- a/datalab/gui/processor/image.py +++ b/datalab/gui/processor/image.py @@ -37,6 +37,9 @@ from datalab.objectmodel import get_uuid from datalab.utils.qthelpers import create_progress_bar, qt_try_except from datalab.widgets import imagebackground +from datalab.widgets.replacespecialvalues import ( + ReplaceSpecialValuesImageParamDL, +) def apply_geometry_transform( @@ -432,6 +435,12 @@ def register_processing(self) -> None: icon_name="normalize.svg", ) self.register_1_to_1(sipi.clip, _("Clipping"), sipb.ClipParam, "clip.svg") + self.register_1_to_1( + sipi.replace_special_values, + _("Replace special values"), + ReplaceSpecialValuesImageParamDL, + "replace_nan.svg", + ) self.register_1_to_1( sipi.offset_correction, _("Offset correction"), diff --git a/datalab/gui/processor/signal.py b/datalab/gui/processor/signal.py index 23094de1..22413171 100644 --- a/datalab/gui/processor/signal.py +++ b/datalab/gui/processor/signal.py @@ -37,6 +37,9 @@ signaldeltax, signalpeak, ) +from datalab.widgets.replacespecialvalues import ( + ReplaceSpecialValuesSignalParamDL, +) class SignalProcessor(BaseProcessor[SignalROI, ROI1DParam]): @@ -233,6 +236,12 @@ def register_processing(self) -> None: self.register_1_to_1( sips.clip, _("Clipping"), sigima_base.ClipParam, "clip.svg" ) + self.register_1_to_1( + sips.replace_special_values, + _("Replace special values"), + ReplaceSpecialValuesSignalParamDL, + "replace_nan.svg", + ) self.register_1_to_1( sips.offset_correction, _("Offset correction"), diff --git a/datalab/widgets/replacespecialvalues.py b/datalab/widgets/replacespecialvalues.py new file mode 100644 index 00000000..025ae8cc --- /dev/null +++ b/datalab/widgets/replacespecialvalues.py @@ -0,0 +1,408 @@ +# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file. + +""" +Replace special values dialog +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Custom dialog widget for the "Replace special values" feature. +Provides count display, kernel visualization, and enhanced parameter editing. + +Features implemented: +- **Count display** (Point 4): colored badges showing NaN / +Inf / -Inf counts. +- **Kernel preview** (Point 6): visual grid of the active neighbor mask. +- **Effect preview** (Point 2): kernel shape updates on parameter change. +- **Custom kernel** (Point 7): string-based kernel input with live preview. +""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import numpy as np +from guidata.dataset.qtwidgets import DataSetEditLayout +from qtpy import QtCore as QC +from qtpy import QtGui as QG +from qtpy import QtWidgets as QW +from sigima.enums import ReplacementStrategyImage, ReplacementStrategySignal +from sigima.proc.base import ( + ReplaceSpecialValuesImageParam, + ReplaceSpecialValuesSignalParam, +) +from sigima.tools.image.replace_values import count_special_values_2d +from sigima.tools.signal.replace_values import count_special_values + +from datalab.config import _ + +if TYPE_CHECKING: + from qtpy.QtWidgets import QWidget + +# -- Badge configuration -------------------------------------------------------- + +_BADGE_COLORS: dict[str, str] = { + "nan": "#e74c3c", + "posinf": "#e67e22", + "neginf": "#3498db", +} + +_BADGE_LABELS: dict[str, str] = { + "nan": "NaN", + "posinf": "+\u221e", + "neginf": "\u2212\u221e", +} + +# -- Helper widgets ------------------------------------------------------------- + + +def _make_count_badge(key: str, count: int, total: int) -> QW.QLabel: + """Create a rich-text label with a colored dot and count information.""" + color = _BADGE_COLORS[key] + label = _BADGE_LABELS[key] + if total > 0 and count > 0: + pct = count / total * 100 + text = ( + f'\u25cf ' + f"{label}: {count} ({pct:.1f}%)" + ) + else: + text = f'\u25cf {label}: {count}' + lbl = QW.QLabel(text) + lbl.setTextFormat(QC.Qt.RichText) + return lbl + + +class _KernelPreviewWidget(QW.QGroupBox): + """Visual grid showing kernel/mask weights. + + The center cell is highlighted in red, other cells use a blue intensity + proportional to their weight. + """ + + def __init__(self, title: str = "", parent: QWidget | None = None) -> None: + super().__init__(title or _("Kernel / Mask preview"), parent) + layout = QW.QVBoxLayout(self) + self._info = QW.QLabel() + layout.addWidget(self._info) + self._table = QW.QTableWidget() + self._table.setEditTriggers(QW.QAbstractItemView.NoEditTriggers) + self._table.setSelectionMode(QW.QAbstractItemView.NoSelection) + self._table.setMaximumHeight(140) + self._table.verticalHeader().setVisible(False) + self._table.horizontalHeader().setVisible(False) + layout.addWidget(self._table) + self.setVisible(False) + + # -- public API ------------------------------------------------------------- + + def show_1d( + self, kernel: np.ndarray, info: str = "", show_values: bool = True + ) -> None: + """Display a 1-D kernel as a single-row table. + + Args: + kernel: 1-D weight array. + info: label text shown above the table. + show_values: if False, cells show only the coloured background + (useful for non-weighted stat filters like min/max/median). + """ + self._info.setText(info) + n = len(kernel) + self._table.setRowCount(1) + self._table.setColumnCount(n) + center = n // 2 + vmax = float(np.max(np.abs(kernel))) or 1.0 + for c in range(n): + val = kernel[c] + text = f"{val:.3g}" if show_values else "" + item = QW.QTableWidgetItem(text) + item.setTextAlignment(QC.Qt.AlignCenter) + if c == center: + item.setBackground(QG.QColor(255, 180, 180, 200)) + else: + alpha = int(abs(val) / vmax * 180) if show_values else 120 + item.setBackground(QG.QColor(180, 180, 255, alpha)) + self._table.setItem(0, c, item) + self._table.resizeColumnsToContents() + self._table.resizeRowsToContents() + self.setVisible(True) + + def show_2d( + self, kernel: np.ndarray, info: str = "", show_values: bool = True + ) -> None: + """Display a 2-D kernel as a coloured grid. + + Args: + kernel: 2-D weight array. + info: label text shown above the table. + show_values: if False, cells show only the coloured background + (useful for non-weighted stat filters like min/max/median). + """ + self._info.setText(info) + rows, cols = kernel.shape + self._table.setRowCount(rows) + self._table.setColumnCount(cols) + cr, cc = rows // 2, cols // 2 + vmax = float(np.max(np.abs(kernel))) or 1.0 + for r in range(rows): + for c in range(cols): + val = kernel[r, c] + text = f"{val:.3g}" if show_values else "" + item = QW.QTableWidgetItem(text) + item.setTextAlignment(QC.Qt.AlignCenter) + if r == cr and c == cc: + item.setBackground(QG.QColor(255, 180, 180, 200)) + else: + alpha = int(abs(val) / vmax * 180) if show_values else 120 + item.setBackground(QG.QColor(180, 180, 255, alpha)) + self._table.setItem(r, c, item) + self._table.resizeColumnsToContents() + self._table.resizeRowsToContents() + self.setVisible(True) + + def hide_preview(self) -> None: + """Clear and hide the preview group.""" + self._table.setRowCount(0) + self._table.setColumnCount(0) + self.setVisible(False) + + +# -- Main dialog ---------------------------------------------------------------- + + +class ReplaceSpecialValuesDialog(QW.QDialog): + """Custom dialog for the *Replace special values* feature. + + Shows coloured count badges (NaN, +Inf, -Inf) at the top, the standard + DataSet parameter editing form in the middle, and a kernel/mask preview + at the bottom when a neighbor or custom-kernel strategy is selected. + + Args: + instance: DataSet parameter instance to edit. + counts: dictionary with keys ``"nan"``, ``"posinf"``, ``"neginf"``. + total_size: total number of data points. + is_image: ``True`` for image parameters, ``False`` for signals. + parent: parent widget. + """ + + def __init__( + self, + instance: ReplaceSpecialValuesSignalParam | ReplaceSpecialValuesImageParam, + counts: dict[str, int], + total_size: int, + is_image: bool, + parent: QWidget | None = None, + ) -> None: + super().__init__(parent) + self.instance = instance + self._is_image = is_image + self.setWindowTitle(instance.get_title()) + self.setMinimumWidth(480) + + main_layout = QW.QVBoxLayout(self) + + # --- Count badges --- + count_row = QW.QHBoxLayout() + for key in ("nan", "posinf", "neginf"): + count_row.addWidget(_make_count_badge(key, counts[key], total_size)) + count_row.addStretch() + main_layout.addLayout(count_row) + + line = QW.QFrame() + line.setFrameShape(QW.QFrame.HLine) + line.setFrameShadow(QW.QFrame.Sunken) + main_layout.addWidget(line) + + # --- DataSet editing --- + grid = QW.QGridLayout() + self.edit_layout: DataSetEditLayout | None = None + edit_layout = DataSetEditLayout( + self, instance, grid, change_callback=self._on_change + ) + self.edit_layout = edit_layout + main_layout.addLayout(grid) + + # --- Kernel previews (one per group) --- + self._kernel_previews: dict[str, _KernelPreviewWidget] = {} + for key in ("nan", "posinf", "neginf"): + label = _BADGE_LABELS[key] + color = _BADGE_COLORS[key] + preview = _KernelPreviewWidget( + title=_("{label} — Kernel / Mask preview").format(label=label), + ) + preview.setStyleSheet( + f"_KernelPreviewWidget {{ border: 1px solid {color}; }}" + ) + self._kernel_previews[key] = preview + main_layout.addWidget(preview) + + # --- Buttons --- + bbox = QW.QDialogButtonBox(QW.QDialogButtonBox.Ok | QW.QDialogButtonBox.Cancel) + bbox.accepted.connect(self.accept) + bbox.rejected.connect(self.reject) + main_layout.addWidget(bbox) + + # Initial preview + self._refresh_preview() + + # -- internal helpers ------------------------------------------------------- + + def _on_change(self) -> None: + """Slot called whenever a DataSet widget value changes.""" + if self.edit_layout is None: + return + # Sync current widget values → DataSet so the preview reads live data + self.edit_layout.accept_changes() + self._refresh_preview() + + def _refresh_preview(self) -> None: + """Update every kernel preview independently.""" + p = self.instance + for prefix in ("nan", "posinf", "neginf"): + strategy = getattr(p, f"{prefix}_strategy") + name = _BADGE_LABELS[prefix] + preview = self._kernel_previews[prefix] + shown = ( + self._try_show_image_kernel(strategy, prefix, name, preview) + if self._is_image + else self._try_show_signal_kernel(strategy, prefix, name, preview) + ) + if not shown: + preview.hide_preview() + + def _try_show_signal_kernel( + self, + strategy: ReplacementStrategySignal, + prefix: str, + name: str, + preview: _KernelPreviewWidget, + ) -> bool: + """Show kernel for signal neighbor strategies. Returns True if shown.""" + _S = ReplacementStrategySignal + p = self.instance + if strategy in ( + _S.NEIGHBOR_MIN, + _S.NEIGHBOR_MAX, + _S.NEIGHBOR_MEAN, + _S.NEIGHBOR_MEDIAN, + ): + n = getattr(p, f"{prefix}_neighbor_size", 3) + size = 2 * n + 1 + kernel = np.ones(size) / size + show_values = strategy == _S.NEIGHBOR_MEAN + preview.show_1d( + kernel, + _("±{n} points").format(n=n), + show_values=show_values, + ) + return True + return False + + def _try_show_image_kernel( + self, + strategy: ReplacementStrategyImage, + prefix: str, + name: str, + preview: _KernelPreviewWidget, + ) -> bool: + """Show kernel for image neighbor strategies. Returns True if shown.""" + _S = ReplacementStrategyImage + p = self.instance + if strategy in ( + _S.NEIGHBOR_MIN, + _S.NEIGHBOR_MAX, + _S.NEIGHBOR_MEAN, + _S.NEIGHBOR_MEDIAN, + ): + n = getattr(p, f"{prefix}_neighbor_size", 3) + size = 2 * n + 1 + kernel = np.ones((size, size)) / (size * size) + show_values = strategy == _S.NEIGHBOR_MEAN + preview.show_2d( + kernel, + _("±{n} rows × ±{n} columns").format(n=n), + show_values=show_values, + ) + return True + return False + + # -- public interface ------------------------------------------------------- + + def accept(self) -> None: + """Validate all widget values, then commit to the DataSet.""" + if self.edit_layout is not None: + if not self.edit_layout.check_all_values(): + return + self.edit_layout.accept_changes() + super().accept() + + +# -- DataLab-specific parameter subclasses -------------------------------------- + + +class ReplaceSpecialValuesSignalParamDL(ReplaceSpecialValuesSignalParam): + """Signal parameter subclass with counts and custom dialog. + + Overrides :meth:`edit` to display :class:`ReplaceSpecialValuesDialog`. + """ + + _counts: dict[str, int] + _total_size: int + + def update_from_obj(self, obj: object) -> None: + """Pre-analyse the signal to compute special-value counts.""" + _, y = obj.get_data() # type: ignore[union-attr] + self._counts = count_special_values(y) + self._total_size = int(y.size) + + def edit( + self, + parent: QWidget | None = None, + apply: object = None, + wordwrap: bool = True, + size: object = None, + object_name: str | None = None, + ) -> int: + """Open the custom replace-special-values dialog.""" + from guidata.qthelpers import exec_dialog + + counts = getattr(self, "_counts", {"nan": 0, "posinf": 0, "neginf": 0}) + total = getattr(self, "_total_size", 0) + dlg = ReplaceSpecialValuesDialog( + self, counts, total, is_image=False, parent=parent + ) + dlg.setObjectName(object_name or self.__class__.__name__ + "Dialog") + return exec_dialog(dlg) + + +class ReplaceSpecialValuesImageParamDL(ReplaceSpecialValuesImageParam): + """Image parameter subclass with counts and custom dialog. + + Overrides :meth:`edit` to display :class:`ReplaceSpecialValuesDialog`. + """ + + _counts: dict[str, int] + _total_size: int + + def update_from_obj(self, obj: object) -> None: + """Pre-analyse the image to compute special-value counts.""" + data = obj.data.astype(float) # type: ignore[union-attr] + self._counts = count_special_values_2d(data) + self._total_size = int(data.size) + + def edit( + self, + parent: QWidget | None = None, + apply: object = None, + wordwrap: bool = True, + size: object = None, + object_name: str | None = None, + ) -> int: + """Open the custom replace-special-values dialog.""" + from guidata.qthelpers import exec_dialog + + counts = getattr(self, "_counts", {"nan": 0, "posinf": 0, "neginf": 0}) + total = getattr(self, "_total_size", 0) + dlg = ReplaceSpecialValuesDialog( + self, counts, total, is_image=True, parent=parent + ) + dlg.setObjectName(object_name or self.__class__.__name__ + "Dialog") + return exec_dialog(dlg) From 54ec25aa8dc33a9eb30d1f4a62e3d8b34a7861c3 Mon Sep 17 00:00:00 2001 From: Duy Anh Philippe PHAM Date: Thu, 28 May 2026 13:07:34 +0200 Subject: [PATCH 2/4] Feat: Complete replace special values DataLab integration coverage Replace special values is now available through the DataLab processing UI, but users still needed documentation, localized text, release notes, and application coverage around the Sigima-backed computation. This completes the DataLab-facing feature packaging while keeping numerical algorithm validation in Sigima. --- datalab/locale/fr/LC_MESSAGES/datalab.po | 18 + .../image/replace_special_values_app_test.py | 65 + .../signal/replace_special_values_app_test.py | 51 + datalab/widgets/replacespecialvalues.py | 20 +- doc/features/image/menu_processing.rst | 39 + doc/features/signal/menu_processing.rst | 42 + .../features/image/menu_processing.po | 65 +- .../features/signal/menu_processing.po | 80 +- .../LC_MESSAGES/features/validation/status.po | 2056 +++++++++++++++-- .../LC_MESSAGES/release_notes/release_1.02.po | 468 ++++ doc/release_notes/release_1.02.md | 125 + 11 files changed, 2759 insertions(+), 270 deletions(-) create mode 100644 datalab/tests/features/image/replace_special_values_app_test.py create mode 100644 datalab/tests/features/signal/replace_special_values_app_test.py create mode 100644 doc/locale/fr/LC_MESSAGES/release_notes/release_1.02.po create mode 100644 doc/release_notes/release_1.02.md diff --git a/datalab/locale/fr/LC_MESSAGES/datalab.po b/datalab/locale/fr/LC_MESSAGES/datalab.po index 32c7eaa8..ee4592b6 100644 --- a/datalab/locale/fr/LC_MESSAGES/datalab.po +++ b/datalab/locale/fr/LC_MESSAGES/datalab.po @@ -1577,6 +1577,9 @@ msgstr "Normaliser" msgid "Clipping" msgstr "Écrêtage" +msgid "Replace special values" +msgstr "Remplacer les valeurs spéciales" + msgid "Add Gaussian noise" msgstr "Ajouter du bruit gaussien" @@ -3045,6 +3048,21 @@ msgstr "Des journaux de bord ont été générés lors de la dernière session." msgid "Log files are currently empty." msgstr "Les journaux de bord sont vides." +msgid "Kernel / Mask preview" +msgstr "Aperçu du noyau / masque" + +#, python-brace-format +msgid "{label} — Kernel / Mask preview" +msgstr "{label} — Aperçu du noyau / masque" + +#, python-brace-format +msgid "±{n} points" +msgstr "±{n} points" + +#, python-brace-format +msgid "±{n} rows × ±{n} columns" +msgstr "±{n} lignes × ±{n} colonnes" + msgid "Signal baseline selection" msgstr "Sélection de la ligne de base du signal" diff --git a/datalab/tests/features/image/replace_special_values_app_test.py b/datalab/tests/features/image/replace_special_values_app_test.py new file mode 100644 index 00000000..c7db5efa --- /dev/null +++ b/datalab/tests/features/image/replace_special_values_app_test.py @@ -0,0 +1,65 @@ +# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file. + +""" +Replace special values application test for images. + +This test verifies DataLab processor integration for ``replace_special_values``. +Algorithm correctness (including Inf handling) is covered by Sigima unit tests. +Only NaN values are injected here to avoid Qt plot instability with Inf data. +""" + +# pylint: disable=invalid-name # Allows short reference names like x, y, ... +# guitest: show + +from __future__ import annotations + +import numpy as np +import sigima.params +from sigima.enums import ReplacementStrategyImage as S +from sigima.objects import ImageObj, create_image + +from datalab.tests import datalab_test_app_context + + +def test_replace_special_values_image_app(): + """Test image replace special values through DataLab processor.""" + with datalab_test_app_context(console=False) as win: + panel = win.imagepanel + + # Use NaN-only data: Inf values destabilize Qt image plot rendering/teardown + data = np.array( + [ + [1.0, np.nan, 3.0], + [4.0, 5.0, np.nan], + [7.0, 8.0, 9.0], + ] + ) + image = create_image("Image with NaN values", data) + panel.add_object(image) + panel.objview.select_objects([image]) + + param = sigima.params.ReplaceSpecialValuesImageParam.create( + nan_strategy=S.CONSTANT, + nan_constant_value=10.0, + ) + panel.processor.run_feature("replace_special_values", param, edit=False) + + result_objects = panel.objview.get_sel_objects() + assert len(result_objects) == 1 + result = result_objects[0] + assert isinstance(result, ImageObj) + assert not np.isnan(result.data).any() + np.testing.assert_array_equal( + result.data, + np.array( + [ + [1.0, 10.0, 3.0], + [4.0, 5.0, 10.0], + [7.0, 8.0, 9.0], + ] + ), + ) + + +if __name__ == "__main__": + test_replace_special_values_image_app() diff --git a/datalab/tests/features/signal/replace_special_values_app_test.py b/datalab/tests/features/signal/replace_special_values_app_test.py new file mode 100644 index 00000000..e63c0cfa --- /dev/null +++ b/datalab/tests/features/signal/replace_special_values_app_test.py @@ -0,0 +1,51 @@ +# Copyright (c) DataLab Platform Developers, BSD 3-Clause license, see LICENSE file. + +""" +Replace special values application test for signals. + +This test verifies DataLab processor integration for ``replace_special_values``. +Algorithm correctness (including Inf handling) is covered by Sigima unit tests. +Only NaN values are injected here to avoid Qt plot instability with Inf data. +""" + +# pylint: disable=invalid-name # Allows short reference names like x, y, ... +# guitest: show + +from __future__ import annotations + +import numpy as np +import sigima.params +from sigima.enums import ReplacementStrategySignal as S +from sigima.objects import SignalObj, create_signal + +from datalab.tests import datalab_test_app_context + + +def test_replace_special_values_signal_app(): + """Test signal replace special values through DataLab processor.""" + with datalab_test_app_context(console=False) as win: + panel = win.signalpanel + + # Use NaN-only data: Inf values destabilize Qt signal plot rendering + x = np.arange(5, dtype=float) + y = np.array([1.0, np.nan, 3.0, np.nan, 5.0]) + sig = create_signal("Signal with NaN values", x, y) + panel.add_object(sig) + panel.objview.select_objects([sig]) + + param = sigima.params.ReplaceSpecialValuesSignalParam.create( + nan_strategy=S.CONSTANT, + nan_constant_value=10.0, + ) + panel.processor.run_feature("replace_special_values", param, edit=False) + + result_objects = panel.objview.get_sel_objects() + assert len(result_objects) == 1 + result = result_objects[0] + assert isinstance(result, SignalObj) + assert not np.isnan(result.y).any() + np.testing.assert_array_equal(result.y, [1.0, 10.0, 3.0, 10.0, 5.0]) + + +if __name__ == "__main__": + test_replace_special_values_signal_app() diff --git a/datalab/widgets/replacespecialvalues.py b/datalab/widgets/replacespecialvalues.py index 025ae8cc..831d6f4e 100644 --- a/datalab/widgets/replacespecialvalues.py +++ b/datalab/widgets/replacespecialvalues.py @@ -4,14 +4,16 @@ Replace special values dialog ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Custom dialog widget for the "Replace special values" feature. -Provides count display, kernel visualization, and enhanced parameter editing. - -Features implemented: -- **Count display** (Point 4): colored badges showing NaN / +Inf / -Inf counts. -- **Kernel preview** (Point 6): visual grid of the active neighbor mask. -- **Effect preview** (Point 2): kernel shape updates on parameter change. -- **Custom kernel** (Point 7): string-based kernel input with live preview. +Custom dialog widget for the "Replace special values" processing feature. + +The dialog extends the standard guidata DataSet edition layout with: + +- **Count display**: colored badges showing the number (and percentage) of + NaN, +Inf and -Inf samples present in the source signal or image. +- **Kernel preview**: visual grid of the active neighbor mask, displayed + whenever a neighbor-based strategy is selected for any of the three targets. +- **Live preview update**: the kernel preview is refreshed automatically + whenever a parameter value changes. """ from __future__ import annotations @@ -173,7 +175,7 @@ class ReplaceSpecialValuesDialog(QW.QDialog): Shows coloured count badges (NaN, +Inf, -Inf) at the top, the standard DataSet parameter editing form in the middle, and a kernel/mask preview - at the bottom when a neighbor or custom-kernel strategy is selected. + at the bottom when a neighbor-based strategy is selected. Args: instance: DataSet parameter instance to edit. diff --git a/doc/features/image/menu_processing.rst b/doc/features/image/menu_processing.rst index ac499947..41d45964 100644 --- a/doc/features/image/menu_processing.rst +++ b/doc/features/image/menu_processing.rst @@ -124,6 +124,45 @@ Clipping Apply the clipping to each selected image. +Replace special values +~~~~~~~~~~~~~~~~~~~~~~ + +Create a new image where ``NaN``, ``+Inf`` and ``-Inf`` pixels are replaced +using a configurable strategy per target value. + +Each of the three targets (``NaN``, ``+Inf``, ``-Inf``) is handled +independently. For each target the user selects one of the following +strategies (or *Do nothing* to leave the target untouched): + +.. list-table:: + :header-rows: 1 + :widths: 35, 65 + + * - Strategy + - Description + * - Do nothing + - Leave the target values untouched. + * - Replace with zero + - Replace by ``0``. + * - Replace with constant + - Replace by a user-defined constant value. + * - Replace with minimum / maximum + - Replace by the minimum / maximum of the finite pixels. + * - Replace with mean / median + - Replace by the mean / median of the finite pixels. + * - N-neighbor minimum / maximum / mean / median + - Replace by the corresponding statistic computed on the + ``(2N+1) × (2N+1)`` neighborhood around each affected pixel. + +Before opening the standard parameter form, the dialog displays a count of +each target found in the image (e.g. *NaN: 124 (0.5 %)*). When a neighbor +strategy is selected, a small preview shows the 2D kernel that will be used. + +.. note:: + + Unlike for signals, no interpolation strategy is currently available + for images. + Offset correction ~~~~~~~~~~~~~~~~~ diff --git a/doc/features/signal/menu_processing.rst b/doc/features/signal/menu_processing.rst index ca11efe1..c5c71f0c 100644 --- a/doc/features/signal/menu_processing.rst +++ b/doc/features/signal/menu_processing.rst @@ -141,6 +141,48 @@ Clipping Create a new signal which is the result of clipping each selected signal. +Replace special values +~~~~~~~~~~~~~~~~~~~~~~ + +Create a new signal where ``NaN``, ``+Inf`` and ``-Inf`` samples are replaced +using a configurable strategy per target value. + +Each of the three targets (``NaN``, ``+Inf``, ``-Inf``) is handled +independently. For each target the user selects one of the following +strategies (or *Do nothing* to leave the target untouched): + +.. list-table:: + :header-rows: 1 + :widths: 35, 65 + + * - Strategy + - Description + * - Do nothing + - Leave the target values untouched. + * - Replace with zero + - Replace by ``0``. + * - Replace with constant + - Replace by a user-defined constant value. + * - Replace with minimum / maximum + - Replace by the minimum / maximum of the finite samples. + * - Replace with mean / median + - Replace by the mean / median of the finite samples. + * - Delete points + - Remove the affected samples from the signal (the X array is also + shrunk). A warning is emitted if the signal was uniformly sampled. + * - Forward fill / Backward fill + - Propagate the last (resp. next) valid value. + * - Interpolation: Linear / Spline / Quadratic / Cubic / PCHIP + - Reconstruct missing samples by interpolating the surrounding valid + samples. + * - N-neighbor minimum / maximum / mean / median + - Replace by the corresponding statistic computed on the ``2N+1`` + neighboring samples around each affected position. + +Before opening the standard parameter form, the dialog displays a count of +each target found in the signal (e.g. *NaN: 17 (1.7 %)*). When a neighbor +strategy is selected, a small preview shows the kernel that will be used. + Offset correction ~~~~~~~~~~~~~~~~~ diff --git a/doc/locale/fr/LC_MESSAGES/features/image/menu_processing.po b/doc/locale/fr/LC_MESSAGES/features/image/menu_processing.po index 8445bf03..f53cde59 100644 --- a/doc/locale/fr/LC_MESSAGES/features/image/menu_processing.po +++ b/doc/locale/fr/LC_MESSAGES/features/image/menu_processing.po @@ -6,11 +6,11 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: DataLab \n" -"Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Project-Id-Version: datalab\n" +"Report-Msgid-Bugs-To: p.raybaut@codra.fr\n" +"PO-Revision-Date: 2025-05-22 15:46+0200\n" "Language: fr\n" -"Language-Team: fr \n" +"Language-Team: DataLab Platform Developers 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" @@ -179,6 +179,60 @@ msgstr "Ecrêtage" msgid "Apply the clipping to each selected image." msgstr "Applique un écrêtage sur chaque image sélectionnée." +msgid "Replace special values" +msgstr "Remplacer les valeurs spéciales" + +msgid "Create a new image where ``NaN``, ``+Inf`` and ``-Inf`` pixels are replaced using a configurable strategy per target value." +msgstr "Crée une nouvelle image où les pixels ``NaN``, ``+Inf`` et ``-Inf`` sont remplacés à l'aide d'une stratégie configurable pour chaque valeur cible." + +msgid "Each of the three targets (``NaN``, ``+Inf``, ``-Inf``) is handled independently. For each target the user selects one of the following strategies (or *Do nothing* to leave the target untouched):" +msgstr "Chacune des trois cibles (``NaN``, ``+Inf``, ``-Inf``) est traitée indépendamment. Pour chaque cible, l'utilisateur sélectionne l'une des stratégies suivantes (ou *Ne rien faire* pour laisser la cible inchangée) :" + +msgid "Strategy" +msgstr "Stratégie" + +msgid "Do nothing" +msgstr "Ne rien faire" + +msgid "Leave the target values untouched." +msgstr "Laisser les valeurs cibles inchangées." + +msgid "Replace with zero" +msgstr "Remplacer par zéro" + +msgid "Replace by ``0``." +msgstr "Remplacer par ``0``." + +msgid "Replace with constant" +msgstr "Remplacer par une constante" + +msgid "Replace by a user-defined constant value." +msgstr "Remplacer par une valeur constante définie par l'utilisateur." + +msgid "Replace with minimum / maximum" +msgstr "Remplacer par le minimum / maximum" + +msgid "Replace by the minimum / maximum of the finite pixels." +msgstr "Remplacer par le minimum / maximum des pixels finis." + +msgid "Replace with mean / median" +msgstr "Remplacer par la moyenne / médiane" + +msgid "Replace by the mean / median of the finite pixels." +msgstr "Remplacer par la moyenne / médiane des pixels finis." + +msgid "N-neighbor minimum / maximum / mean / median" +msgstr "Minimum / maximum / moyenne / médiane sur N voisins" + +msgid "Replace by the corresponding statistic computed on the ``(2N+1) × (2N+1)`` neighborhood around each affected pixel." +msgstr "Remplacer par la statistique correspondante calculée sur le voisinage ``(2N+1) × (2N+1)`` autour de chaque pixel affecté." + +msgid "Before opening the standard parameter form, the dialog displays a count of each target found in the image (e.g. *NaN: 124 (0.5 %)*). When a neighbor strategy is selected, a small preview shows the 2D kernel that will be used." +msgstr "Avant d'ouvrir le formulaire de paramètres standard, la boîte de dialogue affiche le nombre de chaque cible trouvée dans l'image (par exemple *NaN : 124 (0,5 %)*). Lorsqu'une stratégie fondée sur les voisins est sélectionnée, un petit aperçu montre le noyau 2D qui sera utilisé." + +msgid "Unlike for signals, no interpolation strategy is currently available for images." +msgstr "Contrairement aux signaux, aucune stratégie d'interpolation n'est actuellement disponible pour les images." + msgid "Offset correction" msgstr "Soustraction d'offset" @@ -266,9 +320,6 @@ msgstr "Les paramètres suivants sont disponibles :" msgid "Parameter" msgstr "Paramètre" -msgid "Strategy" -msgstr "Stratégie" - msgid "Zero padding strategy (see below)" msgstr "Stratégie de complément de zéros (voir ci-dessous)" diff --git a/doc/locale/fr/LC_MESSAGES/features/signal/menu_processing.po b/doc/locale/fr/LC_MESSAGES/features/signal/menu_processing.po index 15b98ee9..70e304d3 100644 --- a/doc/locale/fr/LC_MESSAGES/features/signal/menu_processing.po +++ b/doc/locale/fr/LC_MESSAGES/features/signal/menu_processing.po @@ -6,11 +6,11 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: DataLab \n" -"Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Project-Id-Version: datalab\n" +"Report-Msgid-Bugs-To: p.raybaut@codra.fr\n" +"PO-Revision-Date: 2025-05-22 15:46+0200\n" "Language: fr\n" -"Language-Team: fr \n" +"Language-Team: DataLab Platform Developers 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" @@ -199,6 +199,75 @@ msgstr "Ecrêtage" msgid "Create a new signal which is the result of clipping each selected signal." msgstr "Crée un signal à partir de l'écrêtage de chaque signal sélectionné." +msgid "Replace special values" +msgstr "Remplacer les valeurs spéciales" + +msgid "Create a new signal where ``NaN``, ``+Inf`` and ``-Inf`` samples are replaced using a configurable strategy per target value." +msgstr "Crée un nouveau signal où les échantillons ``NaN``, ``+Inf`` et ``-Inf`` sont remplacés à l'aide d'une stratégie configurable pour chaque valeur cible." + +msgid "Each of the three targets (``NaN``, ``+Inf``, ``-Inf``) is handled independently. For each target the user selects one of the following strategies (or *Do nothing* to leave the target untouched):" +msgstr "Chacune des trois cibles (``NaN``, ``+Inf``, ``-Inf``) est traitée indépendamment. Pour chaque cible, l'utilisateur sélectionne l'une des stratégies suivantes (ou *Ne rien faire* pour laisser la cible inchangée) :" + +msgid "Strategy" +msgstr "Stratégie" + +msgid "Do nothing" +msgstr "Ne rien faire" + +msgid "Leave the target values untouched." +msgstr "Laisser les valeurs cibles inchangées." + +msgid "Replace with zero" +msgstr "Remplacer par zéro" + +msgid "Replace by ``0``." +msgstr "Remplacer par ``0``." + +msgid "Replace with constant" +msgstr "Remplacer par une constante" + +msgid "Replace by a user-defined constant value." +msgstr "Remplacer par une valeur constante définie par l'utilisateur." + +msgid "Replace with minimum / maximum" +msgstr "Remplacer par le minimum / maximum" + +msgid "Replace by the minimum / maximum of the finite samples." +msgstr "Remplacer par le minimum / maximum des échantillons finis." + +msgid "Replace with mean / median" +msgstr "Remplacer par la moyenne / médiane" + +msgid "Replace by the mean / median of the finite samples." +msgstr "Remplacer par la moyenne / médiane des échantillons finis." + +msgid "Delete points" +msgstr "Supprimer les points" + +msgid "Remove the affected samples from the signal (the X array is also shrunk). A warning is emitted if the signal was uniformly sampled." +msgstr "Supprimer les échantillons affectés du signal (le tableau X est également réduit). Un avertissement est émis si le signal était échantillonné uniformément." + +msgid "Forward fill / Backward fill" +msgstr "Remplissage avant / remplissage arrière" + +msgid "Propagate the last (resp. next) valid value." +msgstr "Propager la dernière valeur valide (respectivement la suivante)." + +msgid "Interpolation: Linear / Spline / Quadratic / Cubic / PCHIP" +msgstr "Interpolation : linéaire / spline / quadratique / cubique / PCHIP" + +msgid "Reconstruct missing samples by interpolating the surrounding valid samples." +msgstr "Reconstruire les échantillons manquants en interpolant les échantillons valides environnants." + +msgid "N-neighbor minimum / maximum / mean / median" +msgstr "Minimum / maximum / moyenne / médiane sur N voisins" + +msgid "Replace by the corresponding statistic computed on the ``2N+1`` neighboring samples around each affected position." +msgstr "Remplacer par la statistique correspondante calculée sur les ``2N+1`` échantillons voisins autour de chaque position affectée." + +msgid "Before opening the standard parameter form, the dialog displays a count of each target found in the signal (e.g. *NaN: 17 (1.7 %)*). When a neighbor strategy is selected, a small preview shows the kernel that will be used." +msgstr "Avant d'ouvrir le formulaire de paramètres standard, la boîte de dialogue affiche le nombre de chaque cible trouvée dans le signal (par exemple *NaN : 17 (1,7 %)*). Lorsqu'une stratégie fondée sur les voisins est sélectionnée, un petit aperçu montre le noyau qui sera utilisé." + msgid "Offset correction" msgstr "Soustraction d'offset" @@ -283,9 +352,6 @@ msgstr "Crée un signal à partir du complément de zéro de chaque signal séle msgid "The following parameters are available:" msgstr "Les paramètres suivants sont disponibles :" -msgid "Strategy" -msgstr "Stratégie" - msgid "Zero padding strategy (see below)" msgstr "Stratégie de complément de zéro (voir ci-dessous)" diff --git a/doc/locale/fr/LC_MESSAGES/features/validation/status.po b/doc/locale/fr/LC_MESSAGES/features/validation/status.po index a42f6dcc..aa54f39d 100644 --- a/doc/locale/fr/LC_MESSAGES/features/validation/status.po +++ b/doc/locale/fr/LC_MESSAGES/features/validation/status.po @@ -6,19 +6,23 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: DataLab \n" -"Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Project-Id-Version: datalab\n" +"Report-Msgid-Bugs-To: p.raybaut@codra.fr\n" +"PO-Revision-Date: 2025-05-22 15:46+0200\n" "Language: fr\n" -"Language-Team: fr \n" +"Language-Team: DataLab Platform Developers 1);\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.17.0\n" -msgid "Validation in DataLab, the open-source scientific data analysis and visualization platform" -msgstr "Validation dans DataLab, la plateforme open-source d'analyse et de visualisation de données scientifiques" +msgid "" +"Validation in DataLab, the open-source scientific data analysis and " +"visualization platform" +msgstr "" +"Validation dans DataLab, la plateforme open-source d'analyse et de " +"visualisation de données scientifiques" msgid "DataLab, scientific, data, analysis, validation, ground-truth, analytical" msgstr "DataLab, scientifique, données, analyse, validation, analytique" @@ -29,8 +33,12 @@ msgstr "Etat de validation de DataLab" msgid "Functional validation" msgstr "Validation fonctionnelle" -msgid "In DataLab, functional validation is based on a classic test strategy (see :ref:`functional_validation`)." -msgstr "Dans DataLab, la validation fonctionnelle est basée sur une stratégie de test classique (voir :ref:`functional_validation`)." +msgid "" +"In DataLab, functional validation is based on a classic test strategy " +"(see :ref:`functional_validation`)." +msgstr "" +"Dans DataLab, la validation fonctionnelle est basée sur une stratégie de " +"test classique (voir :ref:`functional_validation`)." msgid "Package" msgstr "Package" @@ -62,14 +70,44 @@ msgstr "" msgid "Technical validation" msgstr "Validation technique" -msgid "This paragraph provides the validation status of compute functions in DataLab (this is what we call technical validation, see :ref:`scientific_validation`)." -msgstr "Ce paragraphe fournit l'état de validation des fonctions de calcul dans DataLab (c'est ce que nous appelons validation technique, voir :ref:`scientific_validation`)." +msgid "" +"This paragraph provides the validation status of compute functions in " +"DataLab (this is what we call technical validation, see " +":ref:`scientific_validation`)." +msgstr "" +"Ce paragraphe fournit l'état de validation des fonctions de calcul dans " +"DataLab (c'est ce que nous appelons validation technique, voir " +":ref:`scientific_validation`)." -msgid "This is a work in progress: the tables below are updated continuously as new functions are validated or test code is adapted (the tables are generated from the test code). Some functions are already validated but do not appear in the list below yet, while others are still in the validation process." -msgstr "Il s'agit d'un travail en cours : les tableaux ci-dessous sont mis à jour en continu à mesure que de nouvelles fonctions sont validées ou que le code de test est adapté (les tableaux sont générés à partir du code de test). Certaines fonctions sont déjà validées mais n'apparaissent pas encore dans la liste ci-dessous, tandis que d'autres sont encore en cours de validation." +msgid "" +"This is a work in progress: the tables below are updated continuously as " +"new functions are validated or test code is adapted (the tables are " +"generated from the test code). Some functions are already validated but " +"do not appear in the list below yet, while others are still in the " +"validation process." +msgstr "" +"Il s'agit d'un travail en cours : les tableaux ci-dessous sont mis à jour" +" en continu à mesure que de nouvelles fonctions sont validées ou que le " +"code de test est adapté (les tableaux sont générés à partir du code de " +"test). Certaines fonctions sont déjà validées mais n'apparaissent pas " +"encore dans la liste ci-dessous, tandis que d'autres sont encore en cours" +" de validation." -msgid "The validation status must not be confused with the test coverage. The validation status indicates whether the function has been validated against ground-truth data or analytical models. The test coverage indicates the percentage of the code that is executed by the test suite, but it does not necessarily take into account the correctness of the results (DataLab's test coverage is around 90%)." -msgstr "L'état de validation ne doit pas être confondu avec la couverture de test. L'état de validation indique si la fonction a été validée par rapport à des données de référence ou des modèles analytiques. La couverture de test indique le pourcentage du code qui est exécuté par la suite de tests, mais elle ne prend pas nécessairement en compte la justesse des résultats (la couverture de test de DataLab est d'environ 90%)." +msgid "" +"The validation status must not be confused with the test coverage. The " +"validation status indicates whether the function has been validated " +"against ground-truth data or analytical models. The test coverage " +"indicates the percentage of the code that is executed by the test suite, " +"but it does not necessarily take into account the correctness of the " +"results (DataLab's test coverage is around 90%)." +msgstr "" +"L'état de validation ne doit pas être confondu avec la couverture de " +"test. L'état de validation indique si la fonction a été validée par " +"rapport à des données de référence ou des modèles analytiques. La " +"couverture de test indique le pourcentage du code qui est exécuté par la " +"suite de tests, mais elle ne prend pas nécessairement en compte la " +"justesse des résultats (la couverture de test de DataLab est d'environ " +"90%)." msgid "Validation Statistics" msgstr "Statistiques de validation" @@ -110,8 +148,13 @@ msgstr "" msgid "Signal Compute Functions" msgstr "Fonctions de calcul signal" -msgid "The table below shows the validation status of signal compute functions in DataLab. It is automatically generated from the source code." -msgstr "Le tableau ci-dessous montre l'état de validation des fonctions de calcul signal dans DataLab. Il est généré automatiquement à partir du code source." +msgid "" +"The table below shows the validation status of signal compute functions " +"in DataLab. It is automatically generated from the source code." +msgstr "" +"Le tableau ci-dessous montre l'état de validation des fonctions de calcul" +" signal dans DataLab. Il est généré automatiquement à partir du code " +"source." msgid "Validation status of signal compute functions" msgstr "Etat de validation de DataLab" @@ -131,7 +174,9 @@ msgstr "" msgid "Compute absolute value with :py:data:`numpy.absolute`" msgstr "" -msgid "`test_signal_absolute `_" +msgid "" +"`test_signal_absolute `_" msgstr "" msgid ":py:func:`add_gaussian_noise `" @@ -140,7 +185,9 @@ msgstr "" msgid "Add normal noise to the input signal" msgstr "" -msgid "`test_signal_add_gaussian_noise `_" +msgid "" +"`test_signal_add_gaussian_noise `_" msgstr "" msgid ":py:func:`add_poisson_noise `" @@ -149,7 +196,9 @@ msgstr "" msgid "Add Poisson noise to the input signal" msgstr "" -msgid "`test_signal_add_poisson_noise `_" +msgid "" +"`test_signal_add_poisson_noise `_" msgstr "" msgid ":py:func:`add_uniform_noise `" @@ -158,7 +207,9 @@ msgstr "" msgid "Add uniform noise to the input signal" msgstr "" -msgid "`test_signal_add_uniform_noise `_" +msgid "" +"`test_signal_add_uniform_noise `_" msgstr "" msgid ":py:func:`addition `" @@ -167,7 +218,9 @@ msgstr "" msgid "Compute the element-wise sum of multiple signals" msgstr "" -msgid "`test_signal_addition `_" +msgid "" +"`test_signal_addition `_" msgstr "" msgid ":py:func:`addition_constant `" @@ -176,7 +229,9 @@ msgstr "" msgid "Compute the sum of a signal and a constant value" msgstr "" -msgid "`test_signal_addition_constant `_" +msgid "" +"`test_signal_addition_constant `_" msgstr "" msgid ":py:func:`allan_deviation `" @@ -185,7 +240,9 @@ msgstr "" msgid "Compute Allan deviation" msgstr "Calculer la déviation d'Allan" -msgid "`test_signal_allan_deviation `_" +msgid "" +"`test_signal_allan_deviation `_" msgstr "" msgid ":py:func:`allan_variance `" @@ -194,7 +251,9 @@ msgstr "" msgid "Compute Allan variance" msgstr "" -msgid "`test_signal_allan_variance `_" +msgid "" +"`test_signal_allan_variance `_" msgstr "" msgid ":py:func:`apply_window `" @@ -203,7 +262,9 @@ msgstr "" msgid "Compute windowing" msgstr "Calculer la fenêtrage" -msgid "`test_signal_apply_window `_" +msgid "" +"`test_signal_apply_window `_" msgstr "" msgid ":py:func:`arithmetic `" @@ -212,7 +273,9 @@ msgstr "" msgid "Perform an arithmetic operation on two signals" msgstr "" -msgid "`test_signal_arithmetic `_" +msgid "" +"`test_signal_arithmetic `_" msgstr "" msgid ":py:func:`astype `" @@ -221,7 +284,9 @@ msgstr "" msgid "Convert data type" msgstr "" -msgid "`test_signal_astype `_" +msgid "" +"`test_signal_astype `_" msgstr "" msgid ":py:func:`average `" @@ -230,7 +295,9 @@ msgstr "" msgid "Compute the element-wise average of multiple signals" msgstr "" -msgid "`test_signal_average `_" +msgid "" +"`test_signal_average `_" msgstr "" msgid ":py:func:`bandpass `" @@ -239,7 +306,9 @@ msgstr "" msgid "Compute band-pass filter" msgstr "" -msgid "`test_signal_bandpass `_" +msgid "" +"`test_signal_bandpass `_" msgstr "" msgid ":py:func:`bandstop `" @@ -248,7 +317,9 @@ msgstr "" msgid "Compute band-stop filter" msgstr "" -msgid "`test_signal_bandstop `_" +msgid "" +"`test_signal_bandstop `_" msgstr "" msgid ":py:func:`bandwidth_3db `" @@ -257,7 +328,9 @@ msgstr "" msgid "Compute bandwidth at -3 dB" msgstr "" -msgid "`test_signal_bandwidth_3db `_" +msgid "" +"`test_signal_bandwidth_3db `_" msgstr "" msgid ":py:func:`calibration `" @@ -266,7 +339,9 @@ msgstr "" msgid "Compute linear calibration" msgstr "" -msgid "`test_signal_calibration `_" +msgid "" +"`test_signal_calibration `_" msgstr "" msgid ":py:func:`cdf_fit `" @@ -275,7 +350,9 @@ msgstr "" msgid "Compute CDF fit" msgstr "" -msgid "`test_signal_cdf_fit `_" +msgid "" +"`test_signal_cdf_fit `_" msgstr "" msgid ":py:func:`clip `" @@ -284,25 +361,35 @@ msgstr "" msgid "Compute maximum data clipping" msgstr "" -msgid "`test_signal_clip `_" +msgid "" +"`test_signal_clip `_" msgstr "" -msgid ":py:func:`complex_from_magnitude_phase `" +msgid "" +":py:func:`complex_from_magnitude_phase " +"`" msgstr "" msgid "Combine magnitude and phase signals into a complex signal" msgstr "" -msgid "`test_signal_complex_from_magnitude_phase `_" +msgid "" +"`test_signal_complex_from_magnitude_phase `_" msgstr "" -msgid ":py:func:`complex_from_real_imag `" +msgid "" +":py:func:`complex_from_real_imag " +"`" msgstr "" msgid "Combine two real signals into a complex signal using real + i * imag" msgstr "" -msgid "`test_signal_complex_from_real_imag `_" +msgid "" +"`test_signal_complex_from_real_imag `_" msgstr "" msgid ":py:func:`contrast `" @@ -311,7 +398,9 @@ msgstr "" msgid "Compute contrast" msgstr "Calculer le contraste" -msgid "`test_signal_contrast `_" +msgid "" +"`test_signal_contrast `_" msgstr "" msgid ":py:func:`convolution `" @@ -320,7 +409,9 @@ msgstr "" msgid "Compute convolution of two signals" msgstr "" -msgid "`test_signal_convolution `_" +msgid "" +"`test_signal_convolution `_" msgstr "" msgid ":py:func:`deconvolution `" @@ -329,7 +420,9 @@ msgstr "" msgid "Compute deconvolution" msgstr "Calculer la déconvolution" -msgid "`test_signal_deconvolution `_" +msgid "" +"`test_signal_deconvolution `_" msgstr "" msgid ":py:func:`derivative `" @@ -338,7 +431,9 @@ msgstr "" msgid "Compute derivative" msgstr "Calculer la dérivée" -msgid "`test_signal_derivative `_" +msgid "" +"`test_signal_derivative `_" msgstr "" msgid ":py:func:`detrending `" @@ -347,7 +442,9 @@ msgstr "" msgid "Detrend data" msgstr "" -msgid "`test_signal_detrending `_" +msgid "" +"`test_signal_detrending `_" msgstr "" msgid ":py:func:`difference `" @@ -356,7 +453,9 @@ msgstr "" msgid "Compute the element-wise difference between two signals" msgstr "" -msgid "`test_signal_difference `_" +msgid "" +"`test_signal_difference `_" msgstr "" msgid ":py:func:`difference_constant `" @@ -365,7 +464,9 @@ msgstr "" msgid "Compute the difference between a signal and a constant value" msgstr "" -msgid "`test_signal_difference_constant `_" +msgid "" +"`test_signal_difference_constant `_" msgstr "" msgid ":py:func:`division `" @@ -374,7 +475,9 @@ msgstr "" msgid "Compute the element-wise division between two signals" msgstr "" -msgid "`test_signal_division `_" +msgid "" +"`test_signal_division `_" msgstr "" msgid ":py:func:`division_constant `" @@ -383,7 +486,9 @@ msgstr "" msgid "Compute the division of a signal by a constant value" msgstr "" -msgid "`test_signal_division_constant `_" +msgid "" +"`test_signal_division_constant `_" msgstr "" msgid ":py:func:`dynamic_parameters `" @@ -392,7 +497,9 @@ msgstr "" msgid "Compute Dynamic parameters" msgstr "" -msgid "`test_dynamic_parameters `_" +msgid "" +"`test_dynamic_parameters `_" msgstr "" msgid ":py:func:`evaluate_fit `" @@ -401,7 +508,9 @@ msgstr "" msgid "Evaluate fit function from src1 on the x-axis of src2" msgstr "" -msgid "`test_signal_evaluate_fit `_" +msgid "" +"`test_signal_evaluate_fit `_" msgstr "" msgid ":py:func:`exp `" @@ -410,7 +519,9 @@ msgstr "" msgid "Compute exponential with :py:data:`numpy.exp`" msgstr "" -msgid "`test_signal_exp `_" +msgid "" +"`test_signal_exp `_" msgstr "" msgid ":py:func:`exponential_fit `" @@ -419,16 +530,22 @@ msgstr "" msgid "Compute exponential fit" msgstr "Calculer l'ajustement exponentiel" -msgid "`test_signal_exponential_fit `_" +msgid "" +"`test_signal_exponential_fit `_" msgstr "" -msgid ":py:func:`extract_pulse_features `" +msgid "" +":py:func:`extract_pulse_features " +"`" msgstr "" msgid "Extract pulse features" msgstr "" -msgid "`test_signal_extract_pulse_features `_" +msgid "" +"`test_signal_extract_pulse_features `_" msgstr "" msgid ":py:func:`extract_roi `" @@ -437,7 +554,9 @@ msgstr "" msgid "Extract single region of interest from data" msgstr "" -msgid "`test_signal_extract_roi `_" +msgid "" +"`test_signal_extract_roi `_" msgstr "" msgid ":py:func:`extract_rois `" @@ -446,7 +565,9 @@ msgstr "" msgid "Extract multiple regions of interest from data" msgstr "" -msgid "`test_signal_extract_rois `_" +msgid "" +"`test_signal_extract_rois `_" msgstr "" msgid ":py:func:`fft `" @@ -455,13 +576,17 @@ msgstr "" msgid "Compute FFT" msgstr "Calculer la FFT" -msgid "`test_signal_fft `_" +msgid "" +"`test_signal_fft `_" msgstr "" msgid ":py:func:`full_width_at_y `" msgstr "" -msgid "`test_signal_full_width_at_y `_" +msgid "" +"`test_signal_full_width_at_y `_" msgstr "" msgid ":py:func:`fw1e2 `" @@ -470,7 +595,9 @@ msgstr "" msgid "Compute FW at 1/e²" msgstr "" -msgid "`test_signal_fw1e2 `_" +msgid "" +"`test_signal_fw1e2 `_" msgstr "" msgid ":py:func:`fwhm `" @@ -479,7 +606,9 @@ msgstr "" msgid "Compute FWHM" msgstr "Fonctions de calcul" -msgid "`test_signal_fwhm `_" +msgid "" +"`test_signal_fwhm `_" msgstr "" msgid ":py:func:`gaussian_filter `" @@ -488,7 +617,9 @@ msgstr "" msgid "Compute gaussian filter" msgstr "" -msgid "`test_signal_gaussian_filter `_" +msgid "" +"`test_signal_gaussian_filter `_" msgstr "" msgid ":py:func:`gaussian_fit `" @@ -497,7 +628,9 @@ msgstr "" msgid "Compute Gaussian fit" msgstr "Calculer la déviation d'Allan" -msgid "`test_signal_gaussian_fit `_" +msgid "" +"`test_signal_gaussian_fit `_" msgstr "" msgid ":py:func:`hadamard_variance `" @@ -506,7 +639,9 @@ msgstr "" msgid "Compute Hadamard variance" msgstr "" -msgid "`test_signal_hadamard_variance `_" +msgid "" +"`test_signal_hadamard_variance `_" msgstr "" msgid ":py:func:`highpass `" @@ -515,7 +650,9 @@ msgstr "" msgid "Compute high-pass filter" msgstr "" -msgid "`test_signal_highpass `_" +msgid "" +"`test_signal_highpass `_" msgstr "" msgid ":py:func:`histogram `" @@ -524,7 +661,9 @@ msgstr "" msgid "Compute histogram" msgstr "Calculer l'histogramme" -msgid "`test_signal_histogram `_" +msgid "" +"`test_signal_histogram `_" msgstr "" msgid ":py:func:`ifft `" @@ -533,7 +672,9 @@ msgstr "" msgid "Compute the inverse FFT" msgstr "" -msgid "`test_signal_ifft `_" +msgid "" +"`test_signal_ifft `_" msgstr "" msgid ":py:func:`imag `" @@ -542,7 +683,9 @@ msgstr "" msgid "Compute imaginary part" msgstr "" -msgid "`test_signal_imag `_" +msgid "" +"`test_signal_imag `_" msgstr "" msgid ":py:func:`integral `" @@ -551,7 +694,9 @@ msgstr "" msgid "Compute integral" msgstr "Calculer l'intégrale" -msgid "`test_signal_integral `_" +msgid "" +"`test_signal_integral `_" msgstr "" msgid ":py:func:`interpolate `" @@ -560,7 +705,9 @@ msgstr "" msgid "Interpolate data" msgstr "" -msgid "`test_signal_interpolate `_" +msgid "" +"`test_signal_interpolate `_" msgstr "" msgid ":py:func:`inverse `" @@ -569,7 +716,9 @@ msgstr "" msgid "Compute the element-wise inverse of a signal" msgstr "" -msgid "`test_signal_inverse `_" +msgid "" +"`test_signal_inverse `_" msgstr "" msgid ":py:func:`linear_fit `" @@ -578,7 +727,9 @@ msgstr "" msgid "Compute linear fit" msgstr "Calculer l'ajustement linéaire" -msgid "`test_signal_linear_fit `_" +msgid "" +"`test_signal_linear_fit `_" msgstr "" msgid ":py:func:`log10 `" @@ -587,7 +738,9 @@ msgstr "" msgid "Compute Log10 with :py:data:`numpy.log10`" msgstr "" -msgid "`test_signal_log10 `_" +msgid "" +"`test_signal_log10 `_" msgstr "" msgid ":py:func:`lorentzian_fit `" @@ -596,7 +749,9 @@ msgstr "" msgid "Compute Lorentzian fit" msgstr "Calculer l'ajustement lorentzien" -msgid "`test_signal_lorentzian_fit `_" +msgid "" +"`test_signal_lorentzian_fit `_" msgstr "" msgid ":py:func:`lowpass `" @@ -605,7 +760,9 @@ msgstr "" msgid "Compute low-pass filter" msgstr "" -msgid "`test_signal_lowpass `_" +msgid "" +"`test_signal_lowpass `_" msgstr "" msgid ":py:func:`magnitude_spectrum `" @@ -614,16 +771,22 @@ msgstr "" msgid "Compute magnitude spectrum" msgstr "" -msgid "`test_signal_magnitude_spectrum `_" +msgid "" +"`test_signal_magnitude_spectrum `_" msgstr "" -msgid ":py:func:`modified_allan_variance `" +msgid "" +":py:func:`modified_allan_variance " +"`" msgstr "" msgid "Compute Modified Allan variance" msgstr "" -msgid "`test_signal_modified_allan_variance `_" +msgid "" +"`test_signal_modified_allan_variance `_" msgstr "" msgid ":py:func:`moving_average `" @@ -632,7 +795,9 @@ msgstr "" msgid "Compute moving average" msgstr "" -msgid "`test_signal_moving_average `_" +msgid "" +"`test_signal_moving_average `_" msgstr "" msgid ":py:func:`moving_median `" @@ -641,7 +806,9 @@ msgstr "" msgid "Compute moving median" msgstr "" -msgid "`test_signal_moving_median `_" +msgid "" +"`test_signal_moving_median `_" msgstr "" msgid ":py:func:`normalize `" @@ -650,25 +817,35 @@ msgstr "" msgid "Normalize data" msgstr "" -msgid "`test_signal_normalize `_" +msgid "" +"`test_signal_normalize `_" msgstr "" msgid ":py:func:`offset_correction `" msgstr "" -msgid "Correct offset: subtract the mean value of the signal in the specified range" +msgid "" +"Correct offset: subtract the mean value of the signal in the specified " +"range" msgstr "" -msgid "`test_signal_offset_correction `_" +msgid "" +"`test_signal_offset_correction `_" msgstr "" -msgid ":py:func:`overlapping_allan_variance `" +msgid "" +":py:func:`overlapping_allan_variance " +"`" msgstr "" msgid "Compute Overlapping Allan variance" msgstr "" -msgid "`test_signal_overlapping_allan_variance `_" +msgid "" +"`test_signal_overlapping_allan_variance `_" msgstr "" msgid ":py:func:`peak_detection `" @@ -677,7 +854,9 @@ msgstr "" msgid "Peak detection" msgstr "" -msgid "`test_signal_peak_detection `_" +msgid "" +"`test_signal_peak_detection `_" msgstr "" msgid ":py:func:`phase `" @@ -686,7 +865,9 @@ msgstr "" msgid "Compute the phase (argument) of a complex signal" msgstr "" -msgid "`test_signal_phase `_" +msgid "" +"`test_signal_phase `_" msgstr "" msgid ":py:func:`phase_spectrum `" @@ -695,16 +876,22 @@ msgstr "" msgid "Compute phase spectrum" msgstr "" -msgid "`test_signal_phase_spectrum `_" +msgid "" +"`test_signal_phase_spectrum `_" msgstr "" -msgid ":py:func:`piecewiseexponential_fit `" +msgid "" +":py:func:`piecewiseexponential_fit " +"`" msgstr "" msgid "Compute piecewise exponential fit (raise-decay)" msgstr "Calculer l'ajustement exponentiel par morceaux (augmentation-décroissance)" -msgid "`test_signal_piecewiseexponential_fit `_" +msgid "" +"`test_signal_piecewiseexponential_fit `_" msgstr "" msgid ":py:func:`planckian_fit `" @@ -713,7 +900,9 @@ msgstr "" msgid "Compute Planckian fit" msgstr "Calculer l'ajustement de Planck" -msgid "`test_signal_planckian_fit `_" +msgid "" +"`test_signal_planckian_fit `_" msgstr "" msgid ":py:func:`polynomial_fit `" @@ -722,7 +911,9 @@ msgstr "" msgid "Compute polynomial fit" msgstr "Calculer l'ajustement polynomial" -msgid "`test_polynomial_fit `_" +msgid "" +"`test_polynomial_fit `_" msgstr "" msgid ":py:func:`power `" @@ -731,7 +922,9 @@ msgstr "" msgid "Compute power with :py:data:`numpy.power`" msgstr "" -msgid "`test_signal_power `_" +msgid "" +"`test_signal_power `_" msgstr "" msgid ":py:func:`product `" @@ -740,7 +933,9 @@ msgstr "" msgid "Compute the element-wise product of multiple signals" msgstr "" -msgid "`test_signal_product `_" +msgid "" +"`test_signal_product `_" msgstr "" msgid ":py:func:`product_constant `" @@ -749,7 +944,9 @@ msgstr "" msgid "Compute the product of a signal and a constant value" msgstr "" -msgid "`test_signal_product_constant `_" +msgid "" +"`test_signal_product_constant `_" msgstr "" msgid ":py:func:`psd `" @@ -758,7 +955,9 @@ msgstr "" msgid "Compute power spectral density" msgstr "" -msgid "`test_signal_psd `_" +msgid "" +"`test_signal_psd `_" msgstr "" msgid ":py:func:`quadratic_difference `" @@ -767,7 +966,9 @@ msgstr "" msgid "Compute the normalized difference between two signals" msgstr "" -msgid "`test_signal_quadratic_difference `_" +msgid "" +"`test_signal_quadratic_difference `_" msgstr "" msgid ":py:func:`real `" @@ -776,7 +977,9 @@ msgstr "" msgid "Compute real part" msgstr "Calculer la partie réelle" -msgid "`test_signal_real `_" +msgid "" +"`test_signal_real `_" msgstr "" msgid ":py:func:`replace_x_by_other_y `" @@ -785,7 +988,9 @@ msgstr "" msgid "Create a new signal using Y from src1 and Y from src2 as X coordinates" msgstr "" -msgid "`test_replace_x_by_other_y `_" +msgid "" +"`test_replace_x_by_other_y `_" msgstr "" msgid ":py:func:`resampling `" @@ -794,7 +999,9 @@ msgstr "" msgid "Resample data" msgstr "" -msgid "`test_signal_resampling `_" +msgid "" +"`test_signal_resampling `_" msgstr "" msgid ":py:func:`reverse_x `" @@ -803,7 +1010,9 @@ msgstr "" msgid "Reverse x-axis" msgstr "" -msgid "`test_signal_reverse_x `_" +msgid "" +"`test_signal_reverse_x `_" msgstr "" msgid ":py:func:`sampling_rate_period `" @@ -812,7 +1021,9 @@ msgstr "" msgid "Compute sampling rate and period" msgstr "" -msgid "`test_signal_sampling_rate_period `_" +msgid "" +"`test_signal_sampling_rate_period `_" msgstr "" msgid ":py:func:`sigmoid_fit `" @@ -821,7 +1032,9 @@ msgstr "" msgid "Compute sigmoid fit" msgstr "Calculer l'ajustement sigmoïde" -msgid "`test_signal_sigmoid_fit `_" +msgid "" +"`test_signal_sigmoid_fit `_" msgstr "" msgid ":py:func:`signals_to_image `" @@ -830,7 +1043,9 @@ msgstr "" msgid "Combine multiple signals into an image" msgstr "" -msgid "`test_signal_signals_to_image `_" +msgid "" +"`test_signal_signals_to_image `_" msgstr "" msgid ":py:func:`sinusoidal_fit `" @@ -839,7 +1054,9 @@ msgstr "" msgid "Compute sinusoidal fit" msgstr "Calculer l'ajustement sinusoïdal" -msgid "`test_sinusoidal_fit `_" +msgid "" +"`test_sinusoidal_fit `_" msgstr "" msgid ":py:func:`sqrt `" @@ -848,7 +1065,9 @@ msgstr "" msgid "Compute square root with :py:data:`numpy.sqrt`" msgstr "" -msgid "`test_signal_sqrt `_" +msgid "" +"`test_signal_sqrt `_" msgstr "" msgid ":py:func:`standard_deviation `" @@ -857,7 +1076,9 @@ msgstr "" msgid "Compute the element-wise standard deviation of multiple signals" msgstr "" -msgid "`test_signal_standard_deviation `_" +msgid "" +"`test_signal_standard_deviation `_" msgstr "" msgid ":py:func:`stats `" @@ -866,7 +1087,9 @@ msgstr "" msgid "Compute statistics on a signal" msgstr "" -msgid "`test_signal_stats_unit `_" +msgid "" +"`test_signal_stats_unit `_" msgstr "" msgid ":py:func:`time_deviation `" @@ -875,7 +1098,9 @@ msgstr "" msgid "Compute Time Deviation (TDEV)" msgstr "" -msgid "`test_signal_time_deviation `_" +msgid "" +"`test_signal_time_deviation `_" msgstr "" msgid ":py:func:`to_cartesian `" @@ -884,7 +1109,9 @@ msgstr "" msgid "Convert polar coordinates to Cartesian coordinates" msgstr "" -msgid "`test_signal_to_cartesian `_" +msgid "" +"`test_signal_to_cartesian `_" msgstr "" msgid ":py:func:`to_polar `" @@ -893,7 +1120,9 @@ msgstr "" msgid "Convert Cartesian coordinates to polar coordinates" msgstr "" -msgid "`test_signal_to_polar `_" +msgid "" +"`test_signal_to_polar `_" msgstr "" msgid ":py:func:`total_variance `" @@ -902,7 +1131,9 @@ msgstr "" msgid "Compute Total variance" msgstr "" -msgid "`test_signal_total_variance `_" +msgid "" +"`test_signal_total_variance `_" msgstr "" msgid ":py:func:`transpose `" @@ -911,7 +1142,9 @@ msgstr "" msgid "Transpose signal (swap X and Y axes)" msgstr "" -msgid "`test_signal_transpose `_" +msgid "" +"`test_signal_transpose `_" msgstr "" msgid ":py:func:`twohalfgaussian_fit `" @@ -920,7 +1153,9 @@ msgstr "" msgid "Compute two-half-Gaussian fit" msgstr "" -msgid "`test_signal_twohalfgaussian_fit `_" +msgid "" +"`test_signal_twohalfgaussian_fit `_" msgstr "" msgid ":py:func:`voigt_fit `" @@ -929,7 +1164,9 @@ msgstr "" msgid "Compute Voigt fit" msgstr "Calculer l'ajustement de Voigt" -msgid "`test_signal_voigt_fit `_" +msgid "" +"`test_signal_voigt_fit `_" msgstr "" msgid ":py:func:`wiener `" @@ -938,19 +1175,25 @@ msgstr "" msgid "Compute Wiener filter" msgstr "" -msgid "`test_signal_wiener `_" +msgid "" +"`test_signal_wiener `_" msgstr "" msgid ":py:func:`x_at_minmax `" msgstr "" -msgid "`test_signal_x_at_minmax `_" +msgid "" +"`test_signal_x_at_minmax `_" msgstr "" msgid ":py:func:`x_at_y `" msgstr "" -msgid "`test_signal_x_at_y `_" +msgid "" +"`test_signal_x_at_y `_" msgstr "" msgid ":py:func:`xy_mode `" @@ -959,13 +1202,17 @@ msgstr "" msgid "Simulate the X-Y mode of an oscilloscope" msgstr "" -msgid "`test_signal_xy_mode `_" +msgid "" +"`test_signal_xy_mode `_" msgstr "" msgid ":py:func:`y_at_x `" msgstr "" -msgid "`test_signal_y_at_x `_" +msgid "" +"`test_signal_y_at_x `_" msgstr "" msgid ":py:func:`zero_padding `" @@ -974,14 +1221,21 @@ msgstr "" msgid "Compute zero padding" msgstr "" -msgid "`test_signal_zero_padding `_" +msgid "" +"`test_signal_zero_padding `_" msgstr "" msgid "Image Compute Functions" msgstr "Fonctions de calcul image" -msgid "The table below shows the validation status of image compute functions in DataLab. It is automatically generated from the source code." -msgstr "Le tableau ci-dessous montre l'état de validation des fonctions de calcul image dans DataLab. Il est généré automatiquement à partir du code source." +msgid "" +"The table below shows the validation status of image compute functions in" +" DataLab. It is automatically generated from the source code." +msgstr "" +"Le tableau ci-dessous montre l'état de validation des fonctions de calcul" +" image dans DataLab. Il est généré automatiquement à partir du code " +"source." msgid "Validation status of image compute functions" msgstr "Etat de validation des fonctions de calcul image" @@ -989,7 +1243,9 @@ msgstr "Etat de validation des fonctions de calcul image" msgid ":py:func:`absolute `" msgstr "" -msgid "`test_image_absolute `_" +msgid "" +"`test_image_absolute `_" msgstr "" msgid ":py:func:`add_gaussian_noise `" @@ -998,7 +1254,9 @@ msgstr "" msgid "Add Gaussian (normal) noise to the input image" msgstr "" -msgid "`test_image_add_gaussian_noise `_" +msgid "" +"`test_image_add_gaussian_noise `_" msgstr "" msgid ":py:func:`add_poisson_noise `" @@ -1007,7 +1265,9 @@ msgstr "" msgid "Add Poisson noise to the input image" msgstr "" -msgid "`test_image_add_poisson_noise `_" +msgid "" +"`test_image_add_poisson_noise `_" msgstr "" msgid ":py:func:`add_uniform_noise `" @@ -1016,7 +1276,9 @@ msgstr "" msgid "Add uniform noise to the input image" msgstr "" -msgid "`test_image_add_uniform_noise `_" +msgid "" +"`test_image_add_uniform_noise `_" msgstr "" msgid ":py:func:`addition `" @@ -1025,7 +1287,9 @@ msgstr "" msgid "Add images in the list and return the result image object" msgstr "" -msgid "`test_image_addition `_" +msgid "" +"`test_image_addition `_" msgstr "" msgid ":py:func:`addition_constant `" @@ -1034,7 +1298,9 @@ msgstr "" msgid "Add **dst** and a constant value and return the new result image object" msgstr "" -msgid "`test_image_addition_constant `_" +msgid "" +"`test_image_addition_constant `_" msgstr "" msgid ":py:func:`adjust_gamma `" @@ -1043,7 +1309,9 @@ msgstr "" msgid "Gamma correction" msgstr "" -msgid "`test_adjust_gamma `_" +msgid "" +"`test_adjust_gamma `_" msgstr "" msgid ":py:func:`adjust_log `" @@ -1052,7 +1320,9 @@ msgstr "" msgid "Compute log correction" msgstr "Calculer l'ajustement logarithmique" -msgid "`test_adjust_log `_" +msgid "" +"`test_adjust_log `_" msgstr "" msgid ":py:func:`adjust_sigmoid `" @@ -1061,7 +1331,9 @@ msgstr "" msgid "Compute sigmoid correction" msgstr "Calculer l'ajustement sigmoïde" -msgid "`test_adjust_sigmoid `_" +msgid "" +"`test_adjust_sigmoid `_" msgstr "" msgid ":py:func:`arithmetic `" @@ -1070,7 +1342,9 @@ msgstr "" msgid "Compute arithmetic operation on two images" msgstr "" -msgid "`test_image_arithmetic `_" +msgid "" +"`test_image_arithmetic `_" msgstr "" msgid ":py:func:`astype `" @@ -1079,16 +1353,22 @@ msgstr "" msgid "Convert image data type" msgstr "" -msgid "`test_image_astype `_" +msgid "" +"`test_image_astype `_" msgstr "" msgid ":py:func:`average `" msgstr "" -msgid "Compute the average of images in the list and return the result image object" +msgid "" +"Compute the average of images in the list and return the result image " +"object" msgstr "" -msgid "`test_image_average `_" +msgid "" +"`test_image_average `_" msgstr "" msgid ":py:func:`average_profile `" @@ -1097,7 +1377,9 @@ msgstr "" msgid "Compute horizontal or vertical average profile" msgstr "" -msgid "`test_average_profile `_" +msgid "" +"`test_average_profile `_" msgstr "" msgid ":py:func:`binning `" @@ -1106,7 +1388,9 @@ msgstr "" msgid "Binning: image pixel binning (or aggregation)" msgstr "" -msgid "`test_binning `_" +msgid "" +"`test_binning `_" msgstr "" msgid ":py:func:`black_tophat `" @@ -1115,7 +1399,9 @@ msgstr "" msgid "Compute Black Top-Hat" msgstr "" -msgid "`test_black_tophat `_" +msgid "" +"`test_black_tophat `_" msgstr "" msgid ":py:func:`blob_dog `" @@ -1124,7 +1410,9 @@ msgstr "" msgid "Compute blobs using Difference of Gaussian method" msgstr "" -msgid "`test_image_blob_dog `_" +msgid "" +"`test_image_blob_dog `_" msgstr "" msgid ":py:func:`blob_doh `" @@ -1133,7 +1421,9 @@ msgstr "" msgid "Compute blobs using Determinant of Hessian method" msgstr "" -msgid "`test_image_blob_doh `_" +msgid "" +"`test_image_blob_doh `_" msgstr "" msgid ":py:func:`blob_log `" @@ -1142,7 +1432,9 @@ msgstr "" msgid "Compute blobs using Laplacian of Gaussian method" msgstr "" -msgid "`test_image_blob_log `_" +msgid "" +"`test_image_blob_log `_" msgstr "" msgid ":py:func:`blob_opencv `" @@ -1151,7 +1443,9 @@ msgstr "" msgid "Compute blobs using OpenCV" msgstr "" -msgid "`test_image_blob_opencv `_" +msgid "" +"`test_image_blob_opencv `_" msgstr "" msgid ":py:func:`butterworth `" @@ -1160,7 +1454,9 @@ msgstr "" msgid "Compute Butterworth filter" msgstr "" -msgid "`test_butterworth `_" +msgid "" +"`test_butterworth `_" msgstr "" msgid ":py:func:`calibration `" @@ -1169,7 +1465,9 @@ msgstr "" msgid "Compute polynomial calibration" msgstr "Calculer l'étalonnage polynomial" -msgid "`test_image_calibration `_" +msgid "" +"`test_image_calibration `_" msgstr "" msgid ":py:func:`canny `" @@ -1178,7 +1476,9 @@ msgstr "" msgid "Compute Canny filter" msgstr "" -msgid "`test_canny `_" +msgid "" +"`test_canny `_" msgstr "" msgid ":py:func:`centroid `" @@ -1187,7 +1487,9 @@ msgstr "" msgid "Compute centroid" msgstr "" -msgid "`test_image_centroid `_" +msgid "" +"`test_image_centroid `_" msgstr "" msgid ":py:func:`clip `" @@ -1196,7 +1498,9 @@ msgstr "" msgid "Apply clipping" msgstr "" -msgid "`test_image_clip `_" +msgid "" +"`test_image_clip `_" msgstr "" msgid ":py:func:`closing `" @@ -1205,35 +1509,46 @@ msgstr "" msgid "Compute morphological closing" msgstr "" -msgid "`test_closing `_" +msgid "" +"`test_closing `_" msgstr "" -msgid ":py:func:`complex_from_magnitude_phase `" +msgid "" +":py:func:`complex_from_magnitude_phase " +"`" msgstr "" msgid "Combine magnitude and phase images into a complex image" msgstr "" -msgid "`test_image_complex_from_magnitude_phase `_" +msgid "" +"`test_image_complex_from_magnitude_phase `_" msgstr "" -msgid ":py:func:`complex_from_real_imag `" +msgid "" +":py:func:`complex_from_real_imag " +"`" msgstr "" msgid "Combine two real images into a complex image using real + i * imag" msgstr "" -msgid "`test_image_complex_from_real_imag `_" +msgid "" +"`test_image_complex_from_real_imag `_" msgstr "" msgid ":py:func:`contour_shape `" msgstr "" -#, fuzzy msgid "Compute contour shape" -msgstr "Calculer le contraste" +msgstr "Calculer la forme du contour" -msgid "`test_contour_shape `_" +msgid "" +"`test_contour_shape `_" msgstr "" msgid ":py:func:`convolution `" @@ -1242,7 +1557,9 @@ msgstr "" msgid "Convolve an image with a kernel" msgstr "" -msgid "`test_image_convolution `_" +msgid "" +"`test_image_convolution `_" msgstr "" msgid ":py:func:`deconvolution `" @@ -1251,7 +1568,9 @@ msgstr "" msgid "Deconvolve a kernel from an image using Fast Fourier Transform (FFT)" msgstr "" -msgid "`test_image_deconvolution `_" +msgid "" +"`test_image_deconvolution `_" msgstr "" msgid ":py:func:`denoise_bilateral `" @@ -1260,7 +1579,9 @@ msgstr "" msgid "Compute bilateral filter denoising" msgstr "" -msgid "`test_denoise_bilateral `_" +msgid "" +"`test_denoise_bilateral `_" msgstr "" msgid ":py:func:`denoise_tophat `" @@ -1269,7 +1590,9 @@ msgstr "" msgid "Denoise using White Top-Hat" msgstr "" -msgid "`test_denoise_tophat `_" +msgid "" +"`test_denoise_tophat `_" msgstr "" msgid ":py:func:`denoise_tv `" @@ -1278,7 +1601,9 @@ msgstr "" msgid "Compute Total Variation denoising" msgstr "" -msgid "`test_denoise_tv `_" +msgid "" +"`test_denoise_tv `_" msgstr "" msgid ":py:func:`denoise_wavelet `" @@ -1287,7 +1612,9 @@ msgstr "" msgid "Compute Wavelet denoising" msgstr "" -msgid "`test_denoise_wavelet `_" +msgid "" +"`test_denoise_wavelet `_" msgstr "" msgid ":py:func:`difference `" @@ -1296,16 +1623,22 @@ msgstr "" msgid "Compute difference between two images" msgstr "" -msgid "`test_image_difference `_" +msgid "" +"`test_image_difference `_" msgstr "" msgid ":py:func:`difference_constant `" msgstr "" -msgid "Subtract a constant value from an image and return the new result image object" +msgid "" +"Subtract a constant value from an image and return the new result image " +"object" msgstr "" -msgid "`test_image_difference_constant `_" +msgid "" +"`test_image_difference_constant `_" msgstr "" msgid ":py:func:`dilation `" @@ -1314,7 +1647,9 @@ msgstr "" msgid "Compute Dilation" msgstr "Calculer la dilatation" -msgid "`test_dilation `_" +msgid "" +"`test_dilation `_" msgstr "" msgid ":py:func:`division `" @@ -1323,7 +1658,9 @@ msgstr "" msgid "Compute division between two images" msgstr "" -msgid "`test_image_division `_" +msgid "" +"`test_image_division `_" msgstr "" msgid ":py:func:`division_constant `" @@ -1332,7 +1669,9 @@ msgstr "" msgid "Divide an image by a constant value and return the new result image object" msgstr "" -msgid "`test_image_division_constant `_" +msgid "" +"`test_image_division_constant `_" msgstr "" msgid ":py:func:`enclosing_circle `" @@ -1341,7 +1680,9 @@ msgstr "" msgid "Compute minimum enclosing circle" msgstr "" -msgid "`test_image_enclosing_circle `_" +msgid "" +"`test_image_enclosing_circle `_" msgstr "" msgid ":py:func:`equalize_adapthist `" @@ -1350,7 +1691,9 @@ msgstr "" msgid "Adaptive histogram equalization" msgstr "" -msgid "`test_equalize_adapthist `_" +msgid "" +"`test_equalize_adapthist `_" msgstr "" msgid ":py:func:`equalize_hist `" @@ -1359,7 +1702,9 @@ msgstr "" msgid "Histogram equalization" msgstr "" -msgid "`test_equalize_hist `_" +msgid "" +"`test_equalize_hist `_" msgstr "" msgid ":py:func:`erase `" @@ -1368,7 +1713,9 @@ msgstr "" msgid "Erase an area of the image using the mean value of the image" msgstr "" -msgid "`test_erase `_" +msgid "" +"`test_erase `_" msgstr "" msgid ":py:func:`erosion `" @@ -1377,13 +1724,17 @@ msgstr "" msgid "Compute Erosion" msgstr "Calculer l'érosion" -msgid "`test_erosion `_" +msgid "" +"`test_erosion `_" msgstr "" msgid ":py:func:`exp `" msgstr "" -msgid "`test_image_exp `_" +msgid "" +"`test_image_exp `_" msgstr "" msgid ":py:func:`extract_roi `" @@ -1392,13 +1743,17 @@ msgstr "" msgid "Extract single ROI" msgstr "" -msgid "`test_image_extract_roi `_" +msgid "" +"`test_image_extract_roi `_" msgstr "" msgid ":py:func:`extract_rois `" msgstr "" -msgid "`test_image_extract_rois `_" +msgid "" +"`test_image_extract_rois `_" msgstr "" msgid ":py:func:`farid `" @@ -1407,7 +1762,9 @@ msgstr "" msgid "Compute Farid filter" msgstr "" -msgid "`test_farid `_" +msgid "" +"`test_farid `_" msgstr "" msgid ":py:func:`farid_h `" @@ -1416,7 +1773,9 @@ msgstr "" msgid "Compute horizontal Farid filter" msgstr "" -msgid "`test_farid_h `_" +msgid "" +"`test_farid_h `_" msgstr "" msgid ":py:func:`farid_v `" @@ -1425,13 +1784,17 @@ msgstr "" msgid "Compute vertical Farid filter" msgstr "" -msgid "`test_farid_v `_" +msgid "" +"`test_farid_v `_" msgstr "" msgid ":py:func:`fft `" msgstr "" -msgid "`test_image_fft `_" +msgid "" +"`test_image_fft `_" msgstr "" msgid ":py:func:`flatfield `" @@ -1440,7 +1803,9 @@ msgstr "" msgid "Compute flat field correction" msgstr "Calculer la correction de champ plat" -msgid "`test_flatfield `_" +msgid "" +"`test_flatfield `_" msgstr "" msgid ":py:func:`fliph `" @@ -1449,7 +1814,9 @@ msgstr "" msgid "Flip data horizontally" msgstr "" -msgid "`test_image_fliph `_" +msgid "" +"`test_image_fliph `_" msgstr "" msgid ":py:func:`flipv `" @@ -1458,13 +1825,17 @@ msgstr "" msgid "Flip data vertically" msgstr "" -msgid "`test_image_flipv `_" +msgid "" +"`test_image_flipv `_" msgstr "" msgid ":py:func:`gaussian_filter `" msgstr "" -msgid "`test_image_gaussian_filter `_" +msgid "" +"`test_image_gaussian_filter `_" msgstr "" msgid ":py:func:`gaussian_freq_filter `" @@ -1473,7 +1844,9 @@ msgstr "" msgid "Apply a Gaussian filter in the frequency domain" msgstr "" -msgid "`test_gaussian_freq_filter `_" +msgid "" +"`test_gaussian_freq_filter `_" msgstr "" msgid ":py:func:`histogram `" @@ -1482,16 +1855,22 @@ msgstr "" msgid "Compute histogram of the image data," msgstr "" -msgid "`test_image_histogram `_" +msgid "" +"`test_image_histogram `_" msgstr "" msgid ":py:func:`horizontal_projection `" msgstr "" -msgid "Compute the sum of pixel intensities along each col. (projection on the x-axis)" +msgid "" +"Compute the sum of pixel intensities along each col. (projection on the " +"x-axis)" msgstr "" -msgid "`test_image_horizontal_projection `_" +msgid "" +"`test_image_horizontal_projection `_" msgstr "" msgid ":py:func:`hough_circle_peaks `" @@ -1500,7 +1879,9 @@ msgstr "" msgid "Compute Hough circles" msgstr "" -msgid "`test_image_hough_circle_peaks `_" +msgid "" +"`test_image_hough_circle_peaks `_" msgstr "" msgid ":py:func:`ifft `" @@ -1509,13 +1890,17 @@ msgstr "" msgid "Compute inverse FFT" msgstr "" -msgid "`test_image_ifft `_" +msgid "" +"`test_image_ifft `_" msgstr "" msgid ":py:func:`imag `" msgstr "" -msgid "`test_image_imag `_" +msgid "" +"`test_image_imag `_" msgstr "" msgid ":py:func:`inverse `" @@ -1524,7 +1909,9 @@ msgstr "" msgid "Compute the inverse of an image and return the new result image object" msgstr "" -msgid "`test_image_inverse `_" +msgid "" +"`test_image_inverse `_" msgstr "" msgid ":py:func:`laplace `" @@ -1533,7 +1920,9 @@ msgstr "" msgid "Compute Laplace filter" msgstr "" -msgid "`test_laplace `_" +msgid "" +"`test_laplace `_" msgstr "" msgid ":py:func:`line_profile `" @@ -1542,7 +1931,9 @@ msgstr "" msgid "Compute horizontal or vertical profile" msgstr "" -msgid "`test_line_profile `_" +msgid "" +"`test_line_profile `_" msgstr "" msgid ":py:func:`log10 `" @@ -1551,7 +1942,9 @@ msgstr "" msgid "Compute log10 with :py:data:`numpy.log10`" msgstr "" -msgid "`test_image_log10 `_" +msgid "" +"`test_image_log10 `_" msgstr "" msgid ":py:func:`log10_z_plus_n `" @@ -1560,31 +1953,41 @@ msgstr "" msgid "Compute log10(z+n) with :py:data:`numpy.log10`" msgstr "" -msgid "`test_image_log10_z_plus_n `_" +msgid "" +"`test_image_log10_z_plus_n `_" msgstr "" msgid ":py:func:`magnitude_spectrum `" msgstr "" -msgid "`test_image_magnitude_spectrum `_" +msgid "" +"`test_image_magnitude_spectrum `_" msgstr "" msgid ":py:func:`moving_average `" msgstr "" -msgid "`test_image_moving_average `_" +msgid "" +"`test_image_moving_average `_" msgstr "" msgid ":py:func:`moving_median `" msgstr "" -msgid "`test_image_moving_median `_" +msgid "" +"`test_image_moving_median `_" msgstr "" msgid ":py:func:`normalize `" msgstr "" -msgid "`test_image_normalize `_" +msgid "" +"`test_image_normalize `_" msgstr "" msgid ":py:func:`offset_correction `" @@ -1593,7 +1996,9 @@ msgstr "" msgid "Apply offset correction" msgstr "" -msgid "`test_image_offset_correction `_" +msgid "" +"`test_image_offset_correction `_" msgstr "" msgid ":py:func:`opening `" @@ -1602,7 +2007,9 @@ msgstr "" msgid "Compute morphological opening" msgstr "" -msgid "`test_opening `_" +msgid "" +"`test_opening `_" msgstr "" msgid ":py:func:`peak_detection `" @@ -1611,7 +2018,9 @@ msgstr "" msgid "Compute 2D peak detection" msgstr "" -msgid "`test_image_peak_detection `_" +msgid "" +"`test_image_peak_detection `_" msgstr "" msgid ":py:func:`phase `" @@ -1620,13 +2029,17 @@ msgstr "" msgid "Compute the phase (argument) of a complex image" msgstr "" -msgid "`test_image_phase `_" +msgid "" +"`test_image_phase `_" msgstr "" msgid ":py:func:`phase_spectrum `" msgstr "" -msgid "`test_image_phase_spectrum `_" +msgid "" +"`test_image_phase_spectrum `_" msgstr "" msgid ":py:func:`prewitt `" @@ -1635,7 +2048,9 @@ msgstr "" msgid "Compute Prewitt filter" msgstr "" -msgid "`test_prewitt `_" +msgid "" +"`test_prewitt `_" msgstr "" msgid ":py:func:`prewitt_h `" @@ -1644,7 +2059,9 @@ msgstr "" msgid "Compute horizontal Prewitt filter" msgstr "" -msgid "`test_prewitt_h `_" +msgid "" +"`test_prewitt_h `_" msgstr "" msgid ":py:func:`prewitt_v `" @@ -1653,7 +2070,9 @@ msgstr "" msgid "Compute vertical Prewitt filter" msgstr "" -msgid "`test_prewitt_v `_" +msgid "" +"`test_prewitt_v `_" msgstr "" msgid ":py:func:`product `" @@ -1662,22 +2081,30 @@ msgstr "" msgid "Multiply images in the list and return the result image object" msgstr "" -msgid "`test_image_product `_" +msgid "" +"`test_image_product `_" msgstr "" msgid ":py:func:`product_constant `" msgstr "" -msgid "Multiply **dst** by a constant value and return the new result image object" +msgid "" +"Multiply **dst** by a constant value and return the new result image " +"object" msgstr "" -msgid "`test_image_product_constant `_" +msgid "" +"`test_image_product_constant `_" msgstr "" msgid ":py:func:`psd `" msgstr "" -msgid "`test_image_psd `_" +msgid "" +"`test_image_psd `_" msgstr "" msgid ":py:func:`quadratic_difference `" @@ -1686,7 +2113,9 @@ msgstr "" msgid "Compute quadratic difference between two images" msgstr "" -msgid "`test_image_quadratic_difference `_" +msgid "" +"`test_image_quadratic_difference `_" msgstr "" msgid ":py:func:`radial_profile `" @@ -1695,13 +2124,17 @@ msgstr "" msgid "Compute radial profile around the centroid" msgstr "" -msgid "`test_radial_profile `_" +msgid "" +"`test_radial_profile `_" msgstr "" msgid ":py:func:`real `" msgstr "" -msgid "`test_image_real `_" +msgid "" +"`test_image_real `_" msgstr "" msgid ":py:func:`resampling `" @@ -1710,7 +2143,9 @@ msgstr "" msgid "Resample image to new coordinate grid using interpolation" msgstr "" -msgid "`test_image_resampling `_" +msgid "" +"`test_image_resampling `_" msgstr "" msgid ":py:func:`rescale_intensity `" @@ -1719,7 +2154,9 @@ msgstr "" msgid "Rescale image intensity levels" msgstr "" -msgid "`test_rescale_intensity `_" +msgid "" +"`test_rescale_intensity `_" msgstr "" msgid ":py:func:`resize `" @@ -1728,7 +2165,9 @@ msgstr "" msgid "Zooming function" msgstr "Fonction de zoom" -msgid "`test_image_resize `_" +msgid "" +"`test_image_resize `_" msgstr "" msgid ":py:func:`roberts `" @@ -1737,7 +2176,9 @@ msgstr "" msgid "Compute Roberts filter" msgstr "" -msgid "`test_roberts `_" +msgid "" +"`test_roberts `_" msgstr "" msgid ":py:func:`rotate `" @@ -1746,7 +2187,9 @@ msgstr "" msgid "Rotate data" msgstr "" -msgid "`test_image_rotate `_" +msgid "" +"`test_image_rotate `_" msgstr "" msgid ":py:func:`rotate270 `" @@ -1755,7 +2198,9 @@ msgstr "" msgid "Rotate data 270°" msgstr "" -msgid "`test_image_rotate270 `_" +msgid "" +"`test_image_rotate270 `_" msgstr "" msgid ":py:func:`rotate90 `" @@ -1764,7 +2209,9 @@ msgstr "" msgid "Rotate data 90°" msgstr "" -msgid "`test_image_rotate90 `_" +msgid "" +"`test_image_rotate90 `_" msgstr "" msgid ":py:func:`scharr `" @@ -1773,7 +2220,9 @@ msgstr "" msgid "Compute Scharr filter" msgstr "" -msgid "`test_scharr `_" +msgid "" +"`test_scharr `_" msgstr "" msgid ":py:func:`scharr_h `" @@ -1782,7 +2231,9 @@ msgstr "" msgid "Compute horizontal Scharr filter" msgstr "" -msgid "`test_scharr_h `_" +msgid "" +"`test_scharr_h `_" msgstr "" msgid ":py:func:`scharr_v `" @@ -1791,7 +2242,9 @@ msgstr "" msgid "Compute vertical Scharr filter" msgstr "" -msgid "`test_scharr_v `_" +msgid "" +"`test_scharr_v `_" msgstr "" msgid ":py:func:`segment_profile `" @@ -1800,7 +2253,9 @@ msgstr "" msgid "Compute segment profile" msgstr "" -msgid "`test_segment_profile `_" +msgid "" +"`test_segment_profile `_" msgstr "" msgid ":py:func:`set_uniform_coords `" @@ -1809,7 +2264,9 @@ msgstr "" msgid "Convert image to uniform coordinate system" msgstr "" -msgid "`test_set_uniform_coords `_" +msgid "" +"`test_set_uniform_coords `_" msgstr "" msgid ":py:func:`sobel `" @@ -1818,7 +2275,9 @@ msgstr "" msgid "Compute Sobel filter" msgstr "" -msgid "`test_sobel `_" +msgid "" +"`test_sobel `_" msgstr "" msgid ":py:func:`sobel_h `" @@ -1827,7 +2286,9 @@ msgstr "" msgid "Compute horizontal Sobel filter" msgstr "" -msgid "`test_sobel_h `_" +msgid "" +"`test_sobel_h `_" msgstr "" msgid ":py:func:`sobel_v `" @@ -1836,7 +2297,9 @@ msgstr "" msgid "Compute vertical Sobel filter" msgstr "" -msgid "`test_sobel_v `_" +msgid "" +"`test_sobel_v `_" msgstr "" msgid ":py:func:`standard_deviation `" @@ -1845,7 +2308,9 @@ msgstr "" msgid "Compute the element-wise standard deviation of multiple images" msgstr "" -msgid "`test_image_standard_deviation `_" +msgid "" +"`test_image_standard_deviation `_" msgstr "" msgid ":py:func:`stats `" @@ -1854,7 +2319,9 @@ msgstr "" msgid "Compute statistics on an image" msgstr "" -msgid "`test_image_stats_unit `_" +msgid "" +"`test_image_stats_unit `_" msgstr "" msgid ":py:func:`threshold `" @@ -1863,7 +2330,9 @@ msgstr "" msgid "Compute the threshold, using one of the available algorithms" msgstr "" -msgid "`test_threshold `_" +msgid "" +"`test_threshold `_" msgstr "" msgid ":py:func:`threshold_isodata `" @@ -1872,7 +2341,9 @@ msgstr "" msgid "Compute the threshold using the Isodata algorithm with default parameters" msgstr "" -msgid "`test_threshold_isodata `_" +msgid "" +"`test_threshold_isodata `_" msgstr "" msgid ":py:func:`threshold_li `" @@ -1881,7 +2352,9 @@ msgstr "" msgid "Compute the threshold using the Li algorithm with default parameters" msgstr "" -msgid "`test_threshold_li `_" +msgid "" +"`test_threshold_li `_" msgstr "" msgid ":py:func:`threshold_mean `" @@ -1890,7 +2363,9 @@ msgstr "" msgid "Compute the threshold using the Mean algorithm" msgstr "" -msgid "`test_threshold_mean `_" +msgid "" +"`test_threshold_mean `_" msgstr "" msgid ":py:func:`threshold_minimum `" @@ -1899,7 +2374,9 @@ msgstr "" msgid "Compute the threshold using the Minimum algorithm with default parameters" msgstr "" -msgid "`test_threshold_minimum `_" +msgid "" +"`test_threshold_minimum `_" msgstr "" msgid ":py:func:`threshold_otsu `" @@ -1908,7 +2385,9 @@ msgstr "" msgid "Compute the threshold using the Otsu algorithm with default parameters" msgstr "" -msgid "`test_threshold_otsu `_" +msgid "" +"`test_threshold_otsu `_" msgstr "" msgid ":py:func:`threshold_triangle `" @@ -1917,7 +2396,9 @@ msgstr "" msgid "Compute the threshold using the Triangle algorithm with default parameters" msgstr "" -msgid "`test_threshold_triangle `_" +msgid "" +"`test_threshold_triangle `_" msgstr "" msgid ":py:func:`threshold_yen `" @@ -1926,7 +2407,9 @@ msgstr "" msgid "Compute the threshold using the Yen algorithm with default parameters" msgstr "" -msgid "`test_threshold_yen `_" +msgid "" +"`test_threshold_yen `_" msgstr "" msgid ":py:func:`translate `" @@ -1935,7 +2418,9 @@ msgstr "" msgid "Translate data" msgstr "" -msgid "`test_image_translate `_" +msgid "" +"`test_image_translate `_" msgstr "" msgid ":py:func:`transpose `" @@ -1944,16 +2429,22 @@ msgstr "" msgid "Transpose image" msgstr "" -msgid "`test_image_transpose `_" +msgid "" +"`test_image_transpose `_" msgstr "" msgid ":py:func:`vertical_projection `" msgstr "" -msgid "Compute the sum of pixel intensities along each row (projection on the y-axis)" +msgid "" +"Compute the sum of pixel intensities along each row (projection on the " +"y-axis)" msgstr "" -msgid "`test_image_vertical_projection `_" +msgid "" +"`test_image_vertical_projection `_" msgstr "" msgid ":py:func:`white_tophat `" @@ -1962,13 +2453,17 @@ msgstr "" msgid "Compute White Top-Hat" msgstr "" -msgid "`test_white_tophat `_" +msgid "" +"`test_white_tophat `_" msgstr "" msgid ":py:func:`wiener `" msgstr "" -msgid "`test_image_wiener `_" +msgid "" +"`test_image_wiener `_" msgstr "" msgid ":py:func:`zero_padding `" @@ -1977,6 +2472,1073 @@ msgstr "" msgid "Zero-padding: add zeros to image borders" msgstr "" -msgid "`test_image_zero_padding `_" -msgstr "" - +msgid "" +"`test_image_zero_padding `_" +msgstr "" + +#~ msgid "" +#~ "`test_signal_absolute `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_add_gaussian_noise `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_add_poisson_noise `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_add_uniform_noise `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_addition `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_addition_constant `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_allan_deviation `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_allan_variance `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_apply_window `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_arithmetic `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_astype `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_average `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_bandpass `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_bandstop `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_bandwidth_3db `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_calibration `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_cdf_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_clip `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_complex_from_magnitude_phase `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_complex_from_real_imag `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_contrast `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_convolution `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_deconvolution `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_derivative `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_detrending `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_difference `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_difference_constant `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_division `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_division_constant `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_dynamic_parameters `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_evaluate_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_exp `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_exponential_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_extract_pulse_features `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_extract_roi `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_extract_rois `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_fft `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_full_width_at_y `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_fw1e2 `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_fwhm `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_gaussian_filter `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_gaussian_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_hadamard_variance `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_highpass `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_histogram `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_ifft `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_imag `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_integral `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_interpolate `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_inverse `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_linear_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_log10 `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_lorentzian_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_lowpass `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_magnitude_spectrum `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_modified_allan_variance `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_moving_average `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_moving_median `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_normalize `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_offset_correction `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_overlapping_allan_variance `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_peak_detection `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_phase `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_phase_spectrum `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_piecewiseexponential_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_planckian_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_polynomial_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_power `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_product `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_product_constant `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_psd `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_quadratic_difference `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_real `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_replace_x_by_other_y `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_resampling `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_reverse_x `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_sampling_rate_period `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_sigmoid_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_signals_to_image `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_sinusoidal_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_sqrt `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_standard_deviation `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_stats_unit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_time_deviation `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_to_cartesian `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_to_polar `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_total_variance `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_transpose `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_twohalfgaussian_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_voigt_fit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_wiener `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_x_at_minmax `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_x_at_y `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_xy_mode `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_y_at_x `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_signal_zero_padding `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_absolute `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_add_gaussian_noise `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_add_poisson_noise `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_add_uniform_noise `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_addition `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_addition_constant `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_adjust_gamma `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_adjust_log `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_adjust_sigmoid `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_arithmetic `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_astype `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_average `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_average_profile `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_binning `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_black_tophat `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_blob_dog `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_blob_doh `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_blob_log `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_blob_opencv `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_butterworth `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_calibration `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_canny `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_centroid `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_clip `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_closing `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_complex_from_magnitude_phase `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_complex_from_real_imag `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_contour_shape `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_convolution `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_deconvolution `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_denoise_bilateral `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_denoise_tophat `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_denoise_tv `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_denoise_wavelet `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_difference `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_difference_constant `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_dilation `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_division `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_division_constant `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_enclosing_circle `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_equalize_adapthist `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_equalize_hist `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_erase `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_erosion `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_exp `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_extract_roi `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_extract_rois `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_farid `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_farid_h `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_farid_v `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_fft `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_flatfield `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_fliph `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_flipv `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_gaussian_filter `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_gaussian_freq_filter `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_histogram `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_horizontal_projection `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_hough_circle_peaks `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_ifft `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_imag `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_inverse `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_laplace `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_line_profile `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_log10 `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_log10_z_plus_n `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_magnitude_spectrum `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_moving_average `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_moving_median `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_normalize `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_offset_correction `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_opening `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_peak_detection `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_phase `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_phase_spectrum `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_prewitt `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_prewitt_h `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_prewitt_v `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_product `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_product_constant `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_psd `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_quadratic_difference `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_radial_profile `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_real `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_resampling `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_rescale_intensity `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_resize `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_roberts `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_rotate `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_rotate270 `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_rotate90 `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_scharr `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_scharr_h `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_scharr_v `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_segment_profile `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_set_uniform_coords `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_sobel `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_sobel_h `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_sobel_v `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_standard_deviation `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_stats_unit `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_threshold `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_threshold_isodata `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_threshold_li `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_threshold_mean `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_threshold_minimum `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_threshold_otsu `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_threshold_triangle `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_threshold_yen `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_translate `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_transpose `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_vertical_projection `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_white_tophat `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_wiener `_" +#~ msgstr "" + +#~ msgid "" +#~ "`test_image_zero_padding `_" +#~ msgstr "" diff --git a/doc/locale/fr/LC_MESSAGES/release_notes/release_1.02.po b/doc/locale/fr/LC_MESSAGES/release_notes/release_1.02.po new file mode 100644 index 00000000..1406b6ca --- /dev/null +++ b/doc/locale/fr/LC_MESSAGES/release_notes/release_1.02.po @@ -0,0 +1,468 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2023, DataLab Platform Developers +# This file is distributed under the same license as the DataLab package. +# FIRST AUTHOR , 2026. +# +msgid "" +msgstr "" +"Project-Id-Version: datalab\n" +"Report-Msgid-Bugs-To: p.raybaut@codra.fr\n" +"PO-Revision-Date: 2025-05-22 15:46+0200\n" +"Language: fr\n" +"Language-Team: DataLab Platform Developers 1);\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.17.0\n" + +msgid "Version 1.2" +msgstr "Version 1.2" + +msgid "DataLab Version 1.2.1" +msgstr "DataLab Version 1.2.1" + +msgid "✨ New Features" +msgstr "✨ Nouvelles fonctionnalités" + +msgid "**Replace special values processing (signal and image):**" +msgstr "**Traitement de remplacement des valeurs spéciales (signal et image) :**" + +msgid "" +"DataLab now provides a dedicated **\"Replace special values\"** " +"processing function that detects and replaces `NaN`, `+Inf` and `-Inf` " +"values in both signals and images. The feature is available under " +"**Processing → Level adjustment → Replace special values** in both the " +"Signal and Image panels." +msgstr "" +"DataLab propose désormais une fonction de traitement dédiée **\"Remplacer les " +"valeurs spéciales\"** qui détecte et remplace les valeurs `NaN`, `+Inf` et " +"`-Inf` dans les signaux comme dans les images. Cette fonctionnalité est " +"disponible sous **Traitement → Ajustement des niveaux → Remplacer les valeurs " +"spéciales** dans les panneaux Signal et Image." + +msgid "" +"Each target (`NaN`, `+Inf`, `-Inf`) can be processed independently with " +"its own strategy" +msgstr "" +"Chaque cible (`NaN`, `+Inf`, `-Inf`) peut être traitée indépendamment avec " +"sa propre stratégie" + +msgid "" +"Signal strategies: do nothing, replace with zero / constant / minimum / " +"maximum / mean / median, delete affected points, forward fill, backward " +"fill, interpolation (linear, spline, quadratic, cubic, PCHIP), N-neighbor" +" minimum / maximum / mean / median" +msgstr "" +"Stratégies pour les signaux : ne rien faire, remplacer par zéro / une " +"constante / le minimum / le maximum / la moyenne / la médiane, supprimer les " +"points concernés, remplissage avant, remplissage arrière, interpolation " +"(linéaire, spline, quadratique, cubique, PCHIP), minimum / maximum / moyenne " +"/ médiane sur N voisins" + +msgid "" +"Image strategies: do nothing, replace with zero / constant / minimum / " +"maximum / mean / median, N-neighbor minimum / maximum / mean / median" +msgstr "" +"Stratégies pour les images : ne rien faire, remplacer par zéro / une " +"constante / le minimum / le maximum / la moyenne / la médiane, minimum / " +"maximum / moyenne / médiane sur N voisins" + +msgid "" +"The parameter dialog displays **colored badges** showing the number (and " +"percentage) of `NaN`, `+Inf` and `-Inf` samples found in the source " +"object, giving immediate visibility on what will be modified" +msgstr "" +"La boîte de dialogue des paramètres affiche des **badges colorés** indiquant " +"le nombre (et le pourcentage) d'échantillons `NaN`, `+Inf` et `-Inf` trouvés " +"dans l'objet source, ce qui permet de voir immédiatement ce qui sera modifié" + +msgid "" +"When a neighbor strategy is selected, a **live kernel preview** shows the" +" shape of the neighborhood that will be used for the replacement" +msgstr "" +"Lorsqu'une stratégie par voisinage est sélectionnée, un **aperçu en direct du " +"noyau** montre la forme du voisinage qui sera utilisé pour le remplacement" + +msgid "🛠️ Bug Fixes" +msgstr "🛠️ Corrections de bugs" + +msgid "**Signal panel menus:**" +msgstr "**Menus du panneau Signal :**" + +msgid "" +"Restored the \"Linear calibration\" entry in the \"Processing > Axis " +"transformation\" menu of the Signal panel - it had been inadvertently " +"dropped during a menu reorganization and was no longer reachable from the" +" menu bar, even though the underlying computation was still available" +msgstr "" +"Restauration de l'entrée \"Étalonnage linéaire\" dans le menu \"Traitement > " +"Transformation des axes\" du panneau Signal : elle avait été supprimée par " +"inadvertance lors d'une réorganisation des menus et n'était plus accessible " +"depuis la barre de menus, même si le calcul sous-jacent restait disponible" + +msgid "**Signal display with uncertainty data:**" +msgstr "**Affichage des signaux avec données d'incertitude :**" + +msgid "" +"Fixed a crash that could occur when displaying a signal whose internal " +"`xydata` array had been expanded to four rows but whose `dx` / `dy` " +"uncertainty rows were entirely `NaN` (no real error bars) — the plot item" +" now correctly receives only the X / Y data in that case, instead of " +"being rejected by PlotPy's `CurveItem.set_data` for receiving four " +"arguments" +msgstr "" +"Correction d'un plantage qui pouvait survenir lors de l'affichage d'un signal " +"dont le tableau interne `xydata` avait été étendu à quatre lignes mais dont " +"les lignes d'incertitude `dx` / `dy` étaient entièrement `NaN` (aucune barre " +"d'erreur réelle) — dans ce cas, l'élément de tracé reçoit désormais " +"correctement uniquement les données X / Y, au lieu d'être rejeté par " +"`CurveItem.set_data` de PlotPy parce qu'il recevait quatre arguments" + +msgid "DataLab Version 1.2.0 (2026-04-20)" +msgstr "DataLab Version 1.2.0 (20/04/2026)" + +msgid "**Plugin configuration dialog:**" +msgstr "**Boîte de dialogue de configuration des plugins :**" + +msgid "" +"DataLab now provides a dedicated **plugin configuration dialog** " +"(accessible via \"Plugins > Configure plugins...\") that gives full " +"control over third-party plugin management:" +msgstr "" +"DataLab propose désormais une **boîte de dialogue de configuration des " +"plugins** dédiée (accessible via \"Plugins > Configurer les plugins...\") " +"offrant un contrôle complet de la gestion des plugins tiers :" + +msgid "" +"Enable or disable individual plugins using checkboxes, or toggle all " +"plugins at once with a tri-state master checkbox" +msgstr "" +"Activer ou désactiver les plugins individuellement à l'aide de cases à " +"cocher, ou basculer tous les plugins d'un coup avec une case maître à trois " +"états" + +msgid "" +"Filter plugins by status: all, enabled, disabled, or plugins with import " +"errors" +msgstr "" +"Filtrer les plugins par état : tous, activés, désactivés ou plugins avec " +"erreurs d'importation" + +msgid "" +"View plugin details including version, author, and expandable long " +"descriptions directly in the dialog" +msgstr "" +"Afficher directement dans la boîte de dialogue les détails des plugins, " +"notamment la version, l'auteur et les descriptions longues extensibles" + +msgid "" +"Plugins with import errors are displayed prominently at the top with " +"their full traceback, making it easy to diagnose installation issues" +msgstr "" +"Les plugins présentant des erreurs d'importation sont affichés en évidence en " +"haut avec leur traceback complet, ce qui facilite le diagnostic des problèmes " +"d'installation" + +msgid "" +"The expandable text widget used for long descriptions computes its " +"preferred width from a fixed measurement context, ensuring stable layout " +"and reliable \"Show full description\" toggling regardless of dialog " +"resizing or offscreen rendering" +msgstr "" +"Le widget de texte extensible utilisé pour les descriptions longues calcule " +"sa largeur préférée à partir d'un contexte de mesure fixe, garantissant une " +"mise en page stable et un basculement fiable de \"Afficher la description " +"complète\", quels que soient le redimensionnement de la boîte de dialogue ou " +"le rendu hors écran" + +msgid "**Plugin hot-reload:**" +msgstr "**Rechargement à chaud des plugins :**" + +msgid "" +"Third-party plugins can now be reloaded at runtime without restarting " +"DataLab, via \"Plugins > Reload plugins\"" +msgstr "" +"Les plugins tiers peuvent désormais être rechargés à l'exécution sans " +"redémarrer DataLab, via \"Plugins > Recharger les plugins\"" + +msgid "" +"Enabling or disabling plugins in the Preferences dialog or plugin " +"configuration dialog takes effect immediately - no restart required" +msgstr "" +"L'activation ou la désactivation de plugins dans la boîte de dialogue des " +"Préférences ou de configuration des plugins prend effet immédiatement — aucun " +"redémarrage n'est nécessaire" + +msgid "" +"The Plugins menu, status widget, and plugin actions are automatically " +"refreshed after configuration changes" +msgstr "" +"Le menu Plugins, le widget d'état et les actions de plugins sont " +"automatiquement actualisés après les changements de configuration" + +msgid "**Multi-instance detection:**" +msgstr "**Détection des instances multiples :**" + +msgid "" +"DataLab now detects when another instance is already running and warns " +"the user before opening a second instance:" +msgstr "" +"DataLab détecte désormais lorsqu'une autre instance est déjà en cours " +"d'exécution et avertit l'utilisateur avant d'ouvrir une seconde instance :" + +msgid "" +"Uses a PID-based lock file mechanism that supports multiple concurrent " +"instances (reference counting)" +msgstr "" +"Utilise un mécanisme de fichier de verrouillage basé sur les PID qui prend en " +"charge plusieurs instances concurrentes (comptage de références)" + +msgid "Stale PIDs from crashed processes are automatically cleaned up" +msgstr "Les PID obsolètes issus de processus ayant planté sont automatiquement nettoyés" + +msgid "" +"Cross-platform support (Windows, macOS, Linux) using platform-specific " +"process detection" +msgstr "" +"Prise en charge multiplateforme (Windows, macOS, Linux) grâce à une détection " +"de processus spécifique à chaque plateforme" + +msgid "" +"Closing one instance no longer incorrectly removes the lock file when " +"other instances are still running" +msgstr "" +"La fermeture d'une instance ne supprime plus à tort le fichier de " +"verrouillage lorsque d'autres instances sont encore en cours d'exécution" + +msgid "**Image ROI editor contrast synchronization:**" +msgstr "**Synchronisation du contraste dans l'éditeur de ROI d'image :**" + +msgid "" +"The image ROI editor now shares contrast (LUT) settings with the source " +"image panel" +msgstr "" +"L'éditeur de ROI d'image partage désormais les réglages de contraste (LUT) " +"avec le panneau d'image source" + +msgid "" +"Adjusting the contrast in the ROI editor is reflected back in the main " +"panel and vice versa" +msgstr "" +"Les ajustements du contraste dans l'éditeur de ROI sont répercutés dans le " +"panneau principal, et inversement" + +msgid "Contrast controls are fully re-enabled in the image ROI editor dialog" +msgstr "" +"Les contrôles de contraste sont entièrement réactivés dans la boîte de " +"dialogue de l'éditeur de ROI d'image" + +msgid "**Remote control API — push modified objects back to DataLab:**" +msgstr "**API de contrôle à distance — renvoi d'objets modifiés vers DataLab :**" + +msgid "" +"The proxy API (XML-RPC and Web API) now exposes a new `set_object` method" +" that updates an existing signal or image in DataLab from a modified copy" +" obtained via `get_object` (fixes [Issue #305](https://github.com" +"/DataLab-Platform/DataLab/issues/305)):" +msgstr "" +"L'API proxy (XML-RPC et API Web) expose désormais une nouvelle méthode " +"`set_object` qui met à jour un signal ou une image existant dans DataLab à " +"partir d'une copie modifiée obtenue via `get_object` (corrige [Issue " +"#305](https://github.com/DataLab-Platform/DataLab/issues/305)) :" + +msgid "" +"Previously, modifications to object properties (e.g. `dx`, `dy`, `x0`, " +"`y0`, `title`) made on the result of `get_object` were lost because " +"`get_object` returns a copy — `set_object` now provides a clean round-" +"trip workflow" +msgstr "" +"Auparavant, les modifications des propriétés d'objet (par ex. `dx`, `dy`, " +"`x0`, `y0`, `title`) effectuées sur le résultat de `get_object` étaient " +"perdues, car `get_object` renvoie une copie — `set_object` fournit désormais " +"un flux de travail aller-retour propre" + +msgid "" +"Works for both signal and image objects: computed result items attached " +"to the object are preserved during the update, so updating an `ImageObj` " +"no longer triggers a type mismatch" +msgstr "" +"Fonctionne pour les objets signal comme image : les éléments de résultats " +"calculés attachés à l'objet sont préservés pendant la mise à jour, de sorte " +"que la mise à jour d'un `ImageObj` ne déclenche plus d'incompatibilité de type" + +msgid "" +"The properties panel is automatically refreshed after `set_object`, so " +"updated object properties (title, units, axes, uncertainties, etc.) are " +"immediately visible in the GUI" +msgstr "" +"Le panneau des propriétés est automatiquement actualisé après `set_object`, " +"de sorte que les propriétés d'objet mises à jour (titre, unités, axes, " +"incertitudes, etc.) sont immédiatement visibles dans l'interface graphique" + +msgid "📖 Documentation" +msgstr "📖 Documentation" + +msgid "Added API documentation for the `datalab.objectmodel` module" +msgstr "Ajout de la documentation de l'API du module `datalab.objectmodel`" + +msgid "" +"Added screenshots for the \"Paste metadata\" dialog (signal and image " +"panels)" +msgstr "" +"Ajout de captures d'écran pour la boîte de dialogue \"Coller les " +"métadonnées\" (panneaux Signal et Image)" + +msgid "" +"Updated plugin documentation to describe the new configuration dialog, " +"hot-reload workflow, and plugin API helpers" +msgstr "" +"Mise à jour de la documentation des plugins pour décrire la nouvelle boîte de " +"dialogue de configuration, le flux de rechargement à chaud et les utilitaires " +"de l'API des plugins" + +msgid "" +"Updated third-party plugin development guide with new template references" +" and test coverage information" +msgstr "" +"Mise à jour du guide de développement des plugins tiers avec de nouvelles " +"références de modèles et des informations sur la couverture de tests" + +#, python-brace-format +msgid "" +"Expanded Web API reference: documented the binary data transfer options " +"(`?compress=false` for faster uncompressed NPZ downloads, " +"`?overwrite=true` for atomic replacement of existing objects), the in-" +"place `PUT /objects/{name}` endpoint that updates an object while " +"preserving its identity, group membership and position, and the new " +"\"Computation\" section listing the `/select` and `/calc` endpoints used " +"to drive DataLab computations remotely" +msgstr "" +"Référence de l'API Web enrichie : documentation des options de transfert de " +"données binaires (`?compress=false` pour des téléchargements NPZ non " +"compressés plus rapides, `?overwrite=true` pour le remplacement atomique " +"d'objets existants), du point d'accès en place `PUT /objects/{name}` qui met " +"à jour un objet tout en préservant son identité, son appartenance au groupe " +"et sa position, ainsi que de la nouvelle section \"Calcul\" listant les " +"points d'accès `/select` et `/calc` utilisés pour piloter les calculs DataLab " +"à distance" + +msgid "" +"Updated French translations across all new and modified documentation " +"pages" +msgstr "" +"Mise à jour des traductions françaises sur toutes les pages de documentation " +"nouvelles ou modifiées" + +msgid "🔧 Improvements" +msgstr "🔧 Améliorations" + +msgid "**Compatibility:**" +msgstr "**Compatibilité :**" + +msgid "" +"Officially support pandas 3.0.x (updated dependency constraint from `< " +"3.0` to `< 3.1`)" +msgstr "" +"Prise en charge officielle de pandas 3.0.x (contrainte de dépendance mise à " +"jour de `< 3.0` à `< 3.1`)" + +msgid "" +"Updated minimum Sigima requirement from 1.1.0 to 1.1.2 to benefit from " +"latest computation engine fixes and improvements" +msgstr "" +"Mise à jour de la version minimale requise de Sigima de 1.1.0 à 1.1.2 afin " +"de bénéficier des derniers correctifs et améliorations du moteur de calcul" + +msgid "" +"Added legacy support for the `WINPYDIRBASE` environment variable for " +"WinPython-based deployments" +msgstr "" +"Ajout de la prise en charge historique de la variable d'environnement " +"`WINPYDIRBASE` pour les déploiements basés sur WinPython" + +msgid "**Plugin system hardening:**" +msgstr "**Renforcement du système de plugins :**" + +msgid "" +"Plugin discovery and registration is now resilient to third-party import " +"failures while preserving error reporting in the console, logs, and " +"configuration dialog" +msgstr "" +"La découverte et l'enregistrement des plugins résistent désormais aux échecs " +"d'importation de plugins tiers tout en conservant le signalement des erreurs " +"dans la console, les journaux et la boîte de dialogue de configuration" + +msgid "" +"Plugin submenus are now scrollable to prevent overflow when many plugin " +"entries are registered" +msgstr "" +"Les sous-menus de plugins peuvent désormais défiler afin d'éviter les " +"débordements lorsque de nombreuses entrées de plugins sont enregistrées" + +msgid "**Development tooling:**" +msgstr "**Outillage de développement :**" + +msgid "" +"New `run_with_env.py` script for running tasks across multiple Python " +"environment contexts (WinPython, venv, etc.)" +msgstr "" +"Nouveau script `run_with_env.py` pour exécuter des tâches dans plusieurs " +"contextes d'environnement Python (WinPython, venv, etc.)" + +msgid "" +"Simplified environment variable handling by removing the " +"`DATALAB_ENV_LOADED` system" +msgstr "" +"Simplification de la gestion des variables d'environnement par suppression du " +"système `DATALAB_ENV_LOADED`" + +msgid "" +"Fixed Coverage full VS Code task to properly use the `run_with_env.py` " +"wrapper" +msgstr "" +"Correction de la tâche VS Code de couverture complète afin d'utiliser " +"correctement le wrapper `run_with_env.py`" + +msgid "**HDF5 workspace - Table serialization:**" +msgstr "**Espace de travail HDF5 — sérialisation des tables :**" + +msgid "" +"Fixed callable metadata not being stripped during HDF5 save/load of " +"`TableResult` objects" +msgstr "" +"Correction des métadonnées appelables qui n'étaient pas supprimées lors de " +"l'enregistrement/chargement HDF5 des objets `TableResult`" + +msgid "" +"Fixed string-based enum values in table results not being restored " +"correctly after HDF5 round-trip" +msgstr "" +"Correction des valeurs d'énumération sous forme de chaînes dans les résultats " +"de table qui n'étaient pas restaurées correctement après un aller-retour HDF5" + +msgid "" +"Fixed `column_formats` attribute not surviving HDF5 round-trip for both " +"`TableResult` and `TableResultBuilder` outputs" +msgstr "" +"Correction de l'attribut `column_formats` qui ne survivait pas à " +"l'aller-retour HDF5 pour les sorties `TableResult` comme `TableResultBuilder`" + +msgid "**Plugin system:**" +msgstr "**Système de plugins :**" + +msgid "" +"Fixed `AttributeError` in plugin configuration dialog when clicking " +"\"Show full description\" (incorrect attribute reference)" +msgstr "" +"Correction d'une `AttributeError` dans la boîte de dialogue de configuration " +"des plugins lors du clic sur \"Afficher la description complète\" (référence " +"d'attribut incorrecte)" + +msgid "" +"Fixed plugin import errors being silently swallowed when they occurred " +"before the internal console was initialized" +msgstr "" +"Correction des erreurs d'importation de plugins qui étaient ignorées " +"silencieusement lorsqu'elles survenaient avant l'initialisation de la console " +"interne" diff --git a/doc/release_notes/release_1.02.md b/doc/release_notes/release_1.02.md new file mode 100644 index 00000000..e6e95509 --- /dev/null +++ b/doc/release_notes/release_1.02.md @@ -0,0 +1,125 @@ +# Version 1.2 # + +## DataLab Version 1.2.1 ## + +### ✨ New Features ### + +**Replace special values processing (signal and image):** + +DataLab now provides a dedicated **"Replace special values"** processing +function that detects and replaces `NaN`, `+Inf` and `-Inf` values in both +signals and images. The feature is available under +**Processing → Level adjustment → Replace special values** in both the Signal +and Image panels. + +* Each target (`NaN`, `+Inf`, `-Inf`) can be processed independently with its + own strategy +* Signal strategies: do nothing, replace with zero / constant / minimum / + maximum / mean / median, delete affected points, forward fill, backward + fill, interpolation (linear, spline, quadratic, cubic, PCHIP), N-neighbor + minimum / maximum / mean / median +* Image strategies: do nothing, replace with zero / constant / minimum / + maximum / mean / median, N-neighbor minimum / maximum / mean / median +* The parameter dialog displays **colored badges** showing the number (and + percentage) of `NaN`, `+Inf` and `-Inf` samples found in the source object, + giving immediate visibility on what will be modified +* When a neighbor strategy is selected, a **live kernel preview** shows the + shape of the neighborhood that will be used for the replacement + +### 🛠️ Bug Fixes ### + +**Signal panel menus:** + +* Restored the "Linear calibration" entry in the "Processing > Axis transformation" menu of the Signal panel - it had been inadvertently dropped during a menu reorganization and was no longer reachable from the menu bar, even though the underlying computation was still available + +**Signal display with uncertainty data:** + +* Fixed a crash that could occur when displaying a signal whose internal + `xydata` array had been expanded to four rows but whose `dx` / `dy` + uncertainty rows were entirely `NaN` (no real error bars) — the plot item + now correctly receives only the X / Y data in that case, instead of being + rejected by PlotPy's `CurveItem.set_data` for receiving four arguments + +## DataLab Version 1.2.0 (2026-04-20) ## + +### ✨ New Features ### + +**Plugin configuration dialog:** + +DataLab now provides a dedicated **plugin configuration dialog** (accessible via "Plugins > Configure plugins...") that gives full control over third-party plugin management: + +* Enable or disable individual plugins using checkboxes, or toggle all plugins at once with a tri-state master checkbox +* Filter plugins by status: all, enabled, disabled, or plugins with import errors +* View plugin details including version, author, and expandable long descriptions directly in the dialog +* Plugins with import errors are displayed prominently at the top with their full traceback, making it easy to diagnose installation issues +* The expandable text widget used for long descriptions computes its preferred width from a fixed measurement context, ensuring stable layout and reliable "Show full description" toggling regardless of dialog resizing or offscreen rendering + +**Plugin hot-reload:** + +* Third-party plugins can now be reloaded at runtime without restarting DataLab, via "Plugins > Reload plugins" +* Enabling or disabling plugins in the Preferences dialog or plugin configuration dialog takes effect immediately - no restart required +* The Plugins menu, status widget, and plugin actions are automatically refreshed after configuration changes + +**Multi-instance detection:** + +DataLab now detects when another instance is already running and warns the user before opening a second instance: + +* Uses a PID-based lock file mechanism that supports multiple concurrent instances (reference counting) +* Stale PIDs from crashed processes are automatically cleaned up +* Cross-platform support (Windows, macOS, Linux) using platform-specific process detection +* Closing one instance no longer incorrectly removes the lock file when other instances are still running + +**Image ROI editor contrast synchronization:** + +* The image ROI editor now shares contrast (LUT) settings with the source image panel +* Adjusting the contrast in the ROI editor is reflected back in the main panel and vice versa +* Contrast controls are fully re-enabled in the image ROI editor dialog + +**Remote control API — push modified objects back to DataLab:** + +The proxy API (XML-RPC and Web API) now exposes a new `set_object` method that updates an existing signal or image in DataLab from a modified copy obtained via `get_object` (fixes [Issue #305](https://github.com/DataLab-Platform/DataLab/issues/305)): + +* Previously, modifications to object properties (e.g. `dx`, `dy`, `x0`, `y0`, `title`) made on the result of `get_object` were lost because `get_object` returns a copy — `set_object` now provides a clean round-trip workflow +* Works for both signal and image objects: computed result items attached to the object are preserved during the update, so updating an `ImageObj` no longer triggers a type mismatch +* The properties panel is automatically refreshed after `set_object`, so updated object properties (title, units, axes, uncertainties, etc.) are immediately visible in the GUI + +### 📖 Documentation ### + +* Added API documentation for the `datalab.objectmodel` module +* Added screenshots for the "Paste metadata" dialog (signal and image panels) +* Updated plugin documentation to describe the new configuration dialog, hot-reload workflow, and plugin API helpers +* Updated third-party plugin development guide with new template references and test coverage information +* Expanded Web API reference: documented the binary data transfer options (`?compress=false` for faster uncompressed NPZ downloads, `?overwrite=true` for atomic replacement of existing objects), the in-place `PUT /objects/{name}` endpoint that updates an object while preserving its identity, group membership and position, and the new "Computation" section listing the `/select` and `/calc` endpoints used to drive DataLab computations remotely +* Updated French translations across all new and modified documentation pages + +### 🔧 Improvements ### + +**Compatibility:** + +* Officially support pandas 3.0.x (updated dependency constraint from `< 3.0` to `< 3.1`) +* Updated minimum Sigima requirement from 1.1.0 to 1.1.2 to benefit from latest computation engine fixes and improvements +* Added legacy support for the `WINPYDIRBASE` environment variable for WinPython-based deployments + +**Plugin system hardening:** + +* Plugin discovery and registration is now resilient to third-party import failures while preserving error reporting in the console, logs, and configuration dialog +* Plugin submenus are now scrollable to prevent overflow when many plugin entries are registered + +**Development tooling:** + +* New `run_with_env.py` script for running tasks across multiple Python environment contexts (WinPython, venv, etc.) +* Simplified environment variable handling by removing the `DATALAB_ENV_LOADED` system +* Fixed Coverage full VS Code task to properly use the `run_with_env.py` wrapper + +### 🛠️ Bug Fixes ### + +**HDF5 workspace - Table serialization:** + +* Fixed callable metadata not being stripped during HDF5 save/load of `TableResult` objects +* Fixed string-based enum values in table results not being restored correctly after HDF5 round-trip +* Fixed `column_formats` attribute not surviving HDF5 round-trip for both `TableResult` and `TableResultBuilder` outputs + +**Plugin system:** + +* Fixed `AttributeError` in plugin configuration dialog when clicking "Show full description" (incorrect attribute reference) +* Fixed plugin import errors being silently swallowed when they occurred before the internal console was initialized From 887d802356f2911c3544526eab1bfafa233c8f93 Mon Sep 17 00:00:00 2001 From: Thomas MALLET Date: Thu, 11 Jun 2026 17:06:46 +0200 Subject: [PATCH 3/4] prevent special value replace for integer image --- .../image/replace_special_values_app_test.py | 43 +++++++++ datalab/widgets/replacespecialvalues.py | 92 ++++++++++++++----- 2 files changed, 113 insertions(+), 22 deletions(-) diff --git a/datalab/tests/features/image/replace_special_values_app_test.py b/datalab/tests/features/image/replace_special_values_app_test.py index c7db5efa..b70d4b14 100644 --- a/datalab/tests/features/image/replace_special_values_app_test.py +++ b/datalab/tests/features/image/replace_special_values_app_test.py @@ -15,10 +15,12 @@ import numpy as np import sigima.params +from qtpy import QtWidgets as QW from sigima.enums import ReplacementStrategyImage as S from sigima.objects import ImageObj, create_image from datalab.tests import datalab_test_app_context +from datalab.widgets.replacespecialvalues import ReplaceSpecialValuesImageParamDL def test_replace_special_values_image_app(): @@ -61,5 +63,46 @@ def test_replace_special_values_image_app(): ) +def test_replace_special_values_integer_image_app_noop(): + """Integer images should keep their data unchanged and emit a warning path.""" + with datalab_test_app_context(console=False) as win: + panel = win.imagepanel + + data = np.arange(9, dtype=np.uint16).reshape(3, 3) + image = create_image("Integer image", data) + panel.add_object(image) + panel.objview.select_objects([image]) + + param = sigima.params.ReplaceSpecialValuesImageParam.create( + nan_strategy=S.CONSTANT, + nan_constant_value=10.0, + ) + panel.processor.run_feature("replace_special_values", param, edit=False) + + result_objects = panel.objview.get_sel_objects() + assert len(result_objects) == 1 + result = result_objects[0] + assert isinstance(result, ImageObj) + assert result is not image + assert result.data.dtype == np.uint16 + np.testing.assert_array_equal(result.data, data) + + +def test_replace_special_values_integer_image_dialog_disabled(): + """The custom dialog should inform the user and disable validation.""" + with datalab_test_app_context(console=False): + data = np.arange(9, dtype=np.uint16).reshape(3, 3) + image = create_image("Integer image", data) + + param = ReplaceSpecialValuesImageParamDL.create() + param.update_from_obj(image) + + dlg = param.create_dialog() + ok_button = dlg.findChild(QW.QDialogButtonBox).button(QW.QDialogButtonBox.Ok) + assert ok_button is not None + assert not ok_button.isEnabled() + dlg.close() + + if __name__ == "__main__": test_replace_special_values_image_app() diff --git a/datalab/widgets/replacespecialvalues.py b/datalab/widgets/replacespecialvalues.py index 831d6f4e..880a9350 100644 --- a/datalab/widgets/replacespecialvalues.py +++ b/datalab/widgets/replacespecialvalues.py @@ -22,6 +22,7 @@ import numpy as np from guidata.dataset.qtwidgets import DataSetEditLayout +from guidata.qthelpers import exec_dialog from qtpy import QtCore as QC from qtpy import QtGui as QG from qtpy import QtWidgets as QW @@ -191,11 +192,15 @@ def __init__( counts: dict[str, int], total_size: int, is_image: bool, + info_message: str | None = None, + can_apply: bool = True, parent: QWidget | None = None, ) -> None: super().__init__(parent) self.instance = instance self._is_image = is_image + self._info_message = info_message + self._can_apply = can_apply self.setWindowTitle(instance.get_title()) self.setMinimumWidth(480) @@ -213,6 +218,15 @@ def __init__( line.setFrameShadow(QW.QFrame.Sunken) main_layout.addWidget(line) + if info_message: + info_label = QW.QLabel(info_message) + info_label.setWordWrap(True) + info_label.setStyleSheet( + "background-color: #eef6ff; border: 1px solid #8fb7e8; " + "padding: 8px; border-radius: 4px;" + ) + main_layout.addWidget(info_label) + # --- DataSet editing --- grid = QW.QGridLayout() self.edit_layout: DataSetEditLayout | None = None @@ -240,6 +254,9 @@ def __init__( bbox = QW.QDialogButtonBox(QW.QDialogButtonBox.Ok | QW.QDialogButtonBox.Cancel) bbox.accepted.connect(self.accept) bbox.rejected.connect(self.reject) + ok_button = bbox.button(QW.QDialogButtonBox.Ok) + if ok_button is not None: + ok_button.setEnabled(can_apply) main_layout.addWidget(bbox) # Initial preview @@ -260,12 +277,11 @@ def _refresh_preview(self) -> None: p = self.instance for prefix in ("nan", "posinf", "neginf"): strategy = getattr(p, f"{prefix}_strategy") - name = _BADGE_LABELS[prefix] preview = self._kernel_previews[prefix] shown = ( - self._try_show_image_kernel(strategy, prefix, name, preview) + self._try_show_image_kernel(strategy, prefix, preview) if self._is_image - else self._try_show_signal_kernel(strategy, prefix, name, preview) + else self._try_show_signal_kernel(strategy, prefix, preview) ) if not shown: preview.hide_preview() @@ -274,7 +290,6 @@ def _try_show_signal_kernel( self, strategy: ReplacementStrategySignal, prefix: str, - name: str, preview: _KernelPreviewWidget, ) -> bool: """Show kernel for signal neighbor strategies. Returns True if shown.""" @@ -302,7 +317,6 @@ def _try_show_image_kernel( self, strategy: ReplacementStrategyImage, prefix: str, - name: str, preview: _KernelPreviewWidget, ) -> bool: """Show kernel for image neighbor strategies. Returns True if shown.""" @@ -330,6 +344,8 @@ def _try_show_image_kernel( def accept(self) -> None: """Validate all widget values, then commit to the DataSet.""" + if not self._can_apply: + return if self.edit_layout is not None: if not self.edit_layout.check_all_values(): return @@ -355,23 +371,30 @@ def update_from_obj(self, obj: object) -> None: self._counts = count_special_values(y) self._total_size = int(y.size) - def edit( + def create_dialog( self, parent: QWidget | None = None, - apply: object = None, - wordwrap: bool = True, - size: object = None, object_name: str | None = None, - ) -> int: - """Open the custom replace-special-values dialog.""" - from guidata.qthelpers import exec_dialog - + ) -> ReplaceSpecialValuesDialog: + """Create the custom replace-special-values dialog.""" counts = getattr(self, "_counts", {"nan": 0, "posinf": 0, "neginf": 0}) total = getattr(self, "_total_size", 0) dlg = ReplaceSpecialValuesDialog( self, counts, total, is_image=False, parent=parent ) dlg.setObjectName(object_name or self.__class__.__name__ + "Dialog") + return dlg + + def edit( + self, + parent: QWidget | None = None, + apply: object = None, + wordwrap: bool = True, + size: object = None, + object_name: str | None = None, + ) -> int: + """Open the custom replace-special-values dialog.""" + dlg = self.create_dialog(parent=parent, object_name=object_name) return exec_dialog(dlg) @@ -383,12 +406,44 @@ class ReplaceSpecialValuesImageParamDL(ReplaceSpecialValuesImageParam): _counts: dict[str, int] _total_size: int + _can_apply: bool + _info_message: str | None def update_from_obj(self, obj: object) -> None: """Pre-analyse the image to compute special-value counts.""" - data = obj.data.astype(float) # type: ignore[union-attr] + data = obj.data # type: ignore[union-attr] self._counts = count_special_values_2d(data) self._total_size = int(data.size) + if np.issubdtype(data.dtype, np.integer): + self._can_apply = False + self._info_message = _( + "This image uses an integer data type, so it cannot contain NaN " + "or infinite values. Replace special values is therefore not " + "applicable." + ) + else: + self._can_apply = True + self._info_message = None + + def create_dialog( + self, + parent: QWidget | None = None, + object_name: str | None = None, + ) -> ReplaceSpecialValuesDialog: + """Create the custom replace-special-values dialog.""" + counts = getattr(self, "_counts", {"nan": 0, "posinf": 0, "neginf": 0}) + total = getattr(self, "_total_size", 0) + dlg = ReplaceSpecialValuesDialog( + self, + counts, + total, + is_image=True, + info_message=getattr(self, "_info_message", None), + can_apply=getattr(self, "_can_apply", True), + parent=parent, + ) + dlg.setObjectName(object_name or self.__class__.__name__ + "Dialog") + return dlg def edit( self, @@ -399,12 +454,5 @@ def edit( object_name: str | None = None, ) -> int: """Open the custom replace-special-values dialog.""" - from guidata.qthelpers import exec_dialog - - counts = getattr(self, "_counts", {"nan": 0, "posinf": 0, "neginf": 0}) - total = getattr(self, "_total_size", 0) - dlg = ReplaceSpecialValuesDialog( - self, counts, total, is_image=True, parent=parent - ) - dlg.setObjectName(object_name or self.__class__.__name__ + "Dialog") + dlg = self.create_dialog(parent=parent, object_name=object_name) return exec_dialog(dlg) From 9510c9dd40f08df265dceb3dcdd05a9311f28264 Mon Sep 17 00:00:00 2001 From: Thomas MALLET Date: Thu, 11 Jun 2026 17:15:09 +0200 Subject: [PATCH 4/4] update translations and release note --- datalab/locale/fr/LC_MESSAGES/datalab.po | 5 +++- .../LC_MESSAGES/release_notes/release_1.03.po | 24 +++++++++++++++++++ doc/release_notes/release_1.03.md | 6 ++++- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/datalab/locale/fr/LC_MESSAGES/datalab.po b/datalab/locale/fr/LC_MESSAGES/datalab.po index c117f684..29991dbb 100644 --- a/datalab/locale/fr/LC_MESSAGES/datalab.po +++ b/datalab/locale/fr/LC_MESSAGES/datalab.po @@ -1677,7 +1677,6 @@ msgstr "Enregistrer l'historique dans un fichier HDF5..." msgid "Save history to a standalone .dlhist file" msgstr "Enregistrer l'historique dans un fichier .dlhist autonome" -#, python-format msgid "Duplicate selected history action/session" msgstr "Dupliquer l'objet %s sélectionné" @@ -4131,6 +4130,9 @@ msgstr "Image" msgid "Dimensions" msgstr "Dimensions" +msgid "This image uses an integer data type, so it cannot contain NaN or infinite values. Replace special values is therefore not applicable." +msgstr "Cette image utilise un type de données entier, elle ne peut donc pas contenir de valeurs NaN ou infinies. Le remplacement des valeurs spéciales n'est donc pas applicable." + msgid "Minimum value" msgstr "Valeur minimum" @@ -4178,3 +4180,4 @@ msgstr "Aucun contour n'a été trouvé pour la plage de niveaux sélectionnée. msgid "Show contour plot..." msgstr "Afficher le tracé de contours..." + diff --git a/doc/locale/fr/LC_MESSAGES/release_notes/release_1.03.po b/doc/locale/fr/LC_MESSAGES/release_notes/release_1.03.po index 6019a429..4e57afc5 100644 --- a/doc/locale/fr/LC_MESSAGES/release_notes/release_1.03.po +++ b/doc/locale/fr/LC_MESSAGES/release_notes/release_1.03.po @@ -34,3 +34,27 @@ msgstr "Les répertoires listés sont ajoutés aux chemins de recherche existant msgid "Non-existent directories are silently skipped (a warning is recorded in the log file), so a stale environment variable on another machine will not prevent DataLab from starting" msgstr "Les répertoires inexistants sont ignorés silencieusement (un avertissement est consigné dans le fichier journal), ainsi une variable d'environnement obsolète sur une autre machine n'empêchera pas le démarrage de DataLab" + +msgid "**Replace special values processing (signal and image):**" +msgstr "**Traitement de remplacement des valeurs spéciales (signal et image) :**" + +msgid "DataLab now provides a dedicated **\"Replace special values\"** processing function that detects and replaces `NaN`, `+Inf` and `-Inf` values in both signals and images. The feature is available under **Processing → Level adjustment → Replace special values** in both the Signal and Image panels." +msgstr "DataLab fournit désormais une fonction de traitement dédiée **\"Remplacer les valeurs spéciales\"** qui détecte et remplace les valeurs `NaN`, `+Inf` et `-Inf` dans les signaux et les images. La fonctionnalité est disponible sous **Traitement → Ajustement des niveaux → Remplacer les valeurs spéciales** dans les panneaux Signal et Image." + +msgid "Each target (`NaN`, `+Inf`, `-Inf`) can be processed independently with its own strategy" +msgstr "Chaque cible (`NaN`, `+Inf`, `-Inf`) peut être traitée indépendamment avec sa propre stratégie" + +msgid "Signal strategies: do nothing, replace with zero / constant / minimum / maximum / mean / median, delete affected points, forward fill, backward fill, interpolation (linear, spline, quadratic, cubic, PCHIP), N-neighbor minimum / maximum / mean / median" +msgstr "Stratégies pour les signaux : ne rien faire, remplacer par zéro / constante / minimum / maximum / moyenne / médiane, supprimer les points affectés, remplissage avant, remplissage arrière, interpolation (linéaire, spline, quadratique, cubique, PCHIP), minimum / maximum / moyenne / médiane des N voisins" + +msgid "Image strategies: do nothing, replace with zero / constant / minimum / maximum / mean / median, N-neighbor minimum / maximum / mean / median" +msgstr "Stratégies pour les images : ne rien faire, remplacer par zéro / constante / minimum / maximum / moyenne / médiane, minimum / maximum / moyenne / médiane des N voisins" + +msgid "The parameter dialog displays **colored badges** showing the number (and percentage) of `NaN`, `+Inf` and `-Inf` samples found in the source object, giving immediate visibility on what will be modified" +msgstr "La boîte de dialogue des paramètres affiche des **badges colorés** indiquant le nombre (et le pourcentage) d'échantillons `NaN`, `+Inf` et `-Inf` trouvés dans l'objet source, offrant une visibilité immédiate sur ce qui sera modifié" + +msgid "When a neighbor strategy is selected, a **live kernel preview** shows the shape of the neighborhood that will be used for the replacement" +msgstr "Lorsqu'une stratégie de voisinage est sélectionnée, un **aperçu en direct du noyau** montre la forme du voisinage qui sera utilisé pour le remplacement" + +msgid "Integer images are handled explicitly: because `NaN` and infinite values cannot exist in integer data, the dialog explains that the operation is not applicable and prevents accidental processing, while preserving the original image data type without unnecessary float conversion" +msgstr "Les images entières sont traitées explicitement : comme les valeurs `NaN` et infinies ne peuvent pas exister dans les données entières, la boîte de dialogue explique que l'opération n'est pas applicable et empêche un traitement accidentel, tout en préservant le type de données d'image d'origine sans conversion inutile en flottant" diff --git a/doc/release_notes/release_1.03.md b/doc/release_notes/release_1.03.md index 0aee9dfe..a4350ccc 100644 --- a/doc/release_notes/release_1.03.md +++ b/doc/release_notes/release_1.03.md @@ -31,4 +31,8 @@ and Image panels. percentage) of `NaN`, `+Inf` and `-Inf` samples found in the source object, giving immediate visibility on what will be modified * When a neighbor strategy is selected, a **live kernel preview** shows the - shape of the neighborhood that will be used for the replacement \ No newline at end of file + shape of the neighborhood that will be used for the replacement +* Integer images are handled explicitly: because `NaN` and infinite values + cannot exist in integer data, the dialog explains that the operation is not + applicable and prevents accidental processing, while preserving the original + image data type without unnecessary float conversion \ No newline at end of file