diff --git a/doc/locale/fr/LC_MESSAGES/release_notes/release_1.01.po b/doc/locale/fr/LC_MESSAGES/release_notes/release_1.01.po index 0819b92..8b721a1 100644 --- a/doc/locale/fr/LC_MESSAGES/release_notes/release_1.01.po +++ b/doc/locale/fr/LC_MESSAGES/release_notes/release_1.01.po @@ -72,6 +72,9 @@ msgstr "La fenêtre d'ajustement planckien part d'une courbe correspondant au pi msgid "The exponential fit dialog now evaluates the same model as Sigima, and its rate slider covers short time constants whatever the X unit (e.g. 1 ms with X in seconds)." msgstr "La fenêtre d'ajustement exponentiel évalue désormais le même modèle que Sigima, et son curseur de taux couvre les constantes de temps courtes quelle que soit l'unité de X (par exemple 1 ms avec X en secondes)." +msgid "Interactive fitting dialogs now open even when their initial automatic fit fails, e.g. on a signal with fewer points than the model parameters: the dialog shows the initial parameter values, which may be adjusted manually. Such a failure used to raise an error, and the dialog was not shown. This closes [Issue #26](https://github.com/DataLab-Platform/SigimaX/issues/26)." +msgstr "Les fenêtres d'ajustement interactif s'ouvrent désormais même lorsque leur ajustement automatique initial échoue, par exemple sur un signal comportant moins de points que le modèle n'a de paramètres : la fenêtre affiche les valeurs initiales des paramètres, qui peuvent être ajustées manuellement. Un tel échec provoquait auparavant une erreur, et la fenêtre ne s'affichait pas. Cela corrige [l'issue #26](https://github.com/DataLab-Platform/SigimaX/issues/26)." + msgid "HDF5 import" msgstr "Import HDF5" diff --git a/doc/release_notes/release_1.01.md b/doc/release_notes/release_1.01.md index 47116bd..e77a655 100644 --- a/doc/release_notes/release_1.01.md +++ b/doc/release_notes/release_1.01.md @@ -36,6 +36,7 @@ * Polynomial and linear fit coefficients are now labelled `a`, `b`, `c`... as in the model formula and in the fitted signal metadata, instead of `c2`, `c1`, `c0`. * The Planckian fit dialog starts from a curve matching the data peak (its initial amplitude was about 147 times too low on blackbody data in physical units), and its "width factor" is now labelled "temperature factor": for wavelengths in meters, the temperature is `h c σ / (5 k_B x₀)`. * The exponential fit dialog now evaluates the same model as Sigima, and its rate slider covers short time constants whatever the X unit (e.g. 1 ms with X in seconds). +* Interactive fitting dialogs now open even when their initial automatic fit fails, e.g. on a signal with fewer points than the model parameters: the dialog shows the initial parameter values, which may be adjusted manually. Such a failure used to raise an error, and the dialog was not shown. This closes [Issue #26](https://github.com/DataLab-Platform/SigimaX/issues/26). ### HDF5 import ### diff --git a/sigimax/tests/widgets/test_fitdialog.py b/sigimax/tests/widgets/test_fitdialog.py index ca48b04..cd23b75 100644 --- a/sigimax/tests/widgets/test_fitdialog.py +++ b/sigimax/tests/widgets/test_fitdialog.py @@ -331,6 +331,46 @@ def reject_dialog(dialog): assert label.textInteractionFlags() & QC.Qt.TextSelectableByMouse +@pytest.mark.parametrize("error", [TypeError, OverflowError, ZeroDivisionError]) +def test_guifit_opens_when_initial_fit_fails(monkeypatch, error): + """`guifit` shows the dialog with the initial values if the initial fit fails.""" + dialogs = [] + + def reject_dialog(dialog): + dialogs.append(dialog) + return False + + def failing_autofit(_dialog): + raise error("initial fit failure") + + monkeypatch.setattr(fdlg, "exec_dialog", reject_dialog) + monkeypatch.setattr(fdlg.FitDialog, "autofit", failing_autofit) + x = np.linspace(0.0, 1.0, 50) + with qt_app_context(): + params = [fdlg.FitParam("a", 1.0, -5.0, 5.0), fdlg.FitParam("b", 0.0, -5, 5)] + result = fdlg.guifit(x, 2.0 * x + 1.0, lambda x, p: p[0] * x + p[1], params) + assert result is None + assert len(dialogs) == 1 + assert [param.value for param in params] == [1.0, 0.0] + + +def test_gaussian_fit_dialog_opens_with_too_few_points(monkeypatch): + """The Gaussian fit dialog opens on fewer points than model parameters. + + The initial least squares fit raises a `TypeError` in this case. + """ + dialogs = [] + + def reject_dialog(dialog): + dialogs.append(dialog) + return False + + monkeypatch.setattr(fdlg, "exec_dialog", reject_dialog) + with qt_app_context(): + assert fdlg.gaussian_fit(np.arange(3.0), np.array([0.0, 1.0, 0.0])) is None + assert len(dialogs) == 1 + + def test_exponential_dialog_reaches_short_time_constants(monkeypatch): """The rate slider reaches b = -1000 for a 1 ms time constant (X in s). diff --git a/sigimax/widgets/fitdialog.py b/sigimax/widgets/fitdialog.py index 142b718..bf50d85 100644 --- a/sigimax/widgets/fitdialog.py +++ b/sigimax/widgets/fitdialog.py @@ -130,7 +130,9 @@ def guifit( win.set_data(x, y, fitfunc, fitparams, fitargs, fitkwargs) try: win.autofit() # TODO: [P3] make this optional - except ValueError: + except Exception: # pylint: disable=broad-except + # The initial fit only gives a better starting point: if it fails (e.g. with + # fewer points than parameters), the dialog shows the initial values pass if parent is None: win.setWindowIcon(get_icon(get_conf().app_logo_path.get()))