Skip to content

BUG: a failing modeling test on windows #18333

Open

Description

@neutrinoceros

example logs
failing test is

astropy\modeling\tests\test_models_quantities.py::test_models_fitting[LMLSQFitter-model33]
Detailed pytest log
__________________ test_models_fitting[LMLSQFitter-model33] ___________________

model = {'bounding_box': False, 'class': <class 'astropy.modeling.functional_models.Sersic2D'>
Name: Sersic2D
N_inputs: 2
N_ou...y / sr>)], 'parameters': {'amplitude': <Quantity 3. MJy / sr>, 'ellip': 0, 'n': 4, 'r_eff': <Quantity 2. arcsec>, ...}}
fitter = <astropy.modeling.fitting.LMLSQFitter object at 0x000001A9E092FBC0>

    @pytest.mark.skipif(not HAS_SCIPY, reason="requires scipy")
    @pytest.mark.filterwarnings(r"ignore:.*:RuntimeWarning")
    @pytest.mark.filterwarnings(r"ignore:Model is linear in parameters.*")
    @pytest.mark.filterwarnings(r"ignore:The fit may be unsuccessful.*")
    @pytest.mark.filterwarnings(r"ignore:humlicek2 has been deprecated since .*")
    @pytest.mark.parametrize("model", MODELS)
    @pytest.mark.parametrize("fitter", fitters)
    def test_models_fitting(model, fitter):
        fitter = fitter()
    
        bad_voigt = model["class"] == Voigt1D and ("method" not in model["parameters"])
        if (
            (
                isinstance(fitter, LevMarLSQFitter)
                and model["class"] in NON_FINITE_LevMar_MODELS
            )
            or (
                isinstance(fitter, TRFLSQFitter)
                and (model["class"] in NON_FINITE_TRF_MODELS or bad_voigt)
            )
            or (
                isinstance(fitter, LMLSQFitter)
                and (model["class"] in NON_FINITE_LM_MODELS or bad_voigt)
            )
            or (
                isinstance(fitter, DogBoxLSQFitter)
                and model["class"] in NON_FINITE_DogBox_MODELS
            )
        ):
            return
    
        m = model["class"](**model["parameters"])
    
        if m.has_bounds and isinstance(fitter, LMLSQFitter):
            pytest.skip("The LMLSQFitter fitter does not support models with bounds")
    
        if len(model["evaluation"][0]) == 2:
            x = np.linspace(1, 3, 100) * model["evaluation"][0][0].unit
            y = np.exp(-(x.value**2)) * model["evaluation"][0][1].unit
            args = [x, y]
        else:
            x = np.linspace(1, 3, 100) * model["evaluation"][0][0].unit
            y = np.linspace(1, 3, 100) * model["evaluation"][0][1].unit
            z = np.exp(-(x.value**2 + y.value**2)) * model["evaluation"][0][2].unit
            args = [x, y, z]
    
        # Test that the model fits even if it has units on parameters
>       m_new = fitter(m, *args)
                ^^^^^^^^^^^^^^^^

..\..\.tox\py312-test-alldeps\Lib\site-packages\astropy\modeling\tests\test_models_quantities.py:837: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
..\..\.tox\py312-test-alldeps\Lib\site-packages\astropy\modeling\fitting.py:275: in wrapper
    model_new = func(self, model, xdata, ydata, zdata, **kwargs)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..\..\.tox\py312-test-alldeps\Lib\site-packages\astropy\modeling\fitting.py:1730: in __call__
    return super().__call__(
..\..\.tox\py312-test-alldeps\Lib\site-packages\astropy\modeling\fitting.py:288: in wrapper
    return func(self, model, x, y, z=z, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..\..\.tox\py312-test-alldeps\Lib\site-packages\astropy\modeling\fitting.py:1429: in __call__
    init_values, fitparams, cov_x = self._run_fitter(
..\..\.tox\py312-test-alldeps\Lib\site-packages\astropy\modeling\fitting.py:1603: in _run_fitter
    self.fit_info = optimize.least_squares(
..\..\.tox\py312-test-alldeps\Lib\site-packages\scipy\_lib\_util.py:689: in inner
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
..\..\.tox\py312-test-alldeps\Lib\site-packages\scipy\optimize\_lsq\least_squares.py:1015: in least_squares
    result = call_minpack(vector_fun.fun, x0, vector_fun.jac, ftol, xtol, gtol,
..\..\.tox\py312-test-alldeps\Lib\site-packages\scipy\optimize\_lsq\least_squares.py:75: in call_minpack
    x, info, status = _minpack._lmder(
..\..\.tox\py312-test-alldeps\Lib\site-packages\scipy\optimize\_differentiable_functions.py:734: in fun
    self._update_fun()
..\..\.tox\py312-test-alldeps\Lib\site-packages\scipy\optimize\_differentiable_functions.py:698: in _update_fun
    self.f = self.fun_wrapped(xp_copy(self.x))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
..\..\.tox\py312-test-alldeps\Lib\site-packages\scipy\optimize\_differentiable_functions.py:415: in __call__
    return np.atleast_1d(self.fun(x))
                         ^^^^^^^^^^^
..\..\.tox\py312-test-alldeps\Lib\site-packages\scipy\optimize\_lsq\least_squares.py:263: in __call__
    return self.f(x, *self.args, **self.kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <astropy.modeling.fitting.LMLSQFitter object at 0x000001A9E092FBC0>
fps = array([   21.14561837,   -19.94026772,  -188.2192972 ,   -45.48335025,
          11.87787074,    21.69193093, -8425.06283925])
fit_param_indices = {0, 1, 2, 3, 4, 5, ...}
args = (<Sersic2D(amplitude=3., r_eff=2., n=4., x_0=1., y_0=2., ellip=0., theta=0.)>, None, array([1.        , 1.02020202, 1.....33342676e-08, 5.01481171e-08, 3.96425452e-08,
       3.12866777e-08, 2.46517859e-08, 1.93922565e-08, 1.52299797e-08]))
model = <Sersic2D(amplitude=3., r_eff=2., n=4., x_0=1., y_0=2., ellip=0., theta=0.)>
weights = None

    def objective_function(self, fps, *args, fit_param_indices=None):
        """
        Function to minimize.
    
        Parameters
        ----------
        fps : list
            parameters returned by the fitter
        args : list
            [model, [weights], [input coordinates]]
        fit_param_indices : list, optional
            The ``fit_param_indices`` as returned by ``model_to_fit_params``.
            This is a list of the parameter indices being fit, so excluding any
            tied or fixed parameters.  This can be passed in to the objective
            function to prevent it having to be computed on every call.
            This must be optional as not all fitters support passing kwargs to
            the objective function.
        """
        model = args[0]
        weights = args[1]
        inputs = args[2:-1]
        meas = args[-1]
    
        fps = fitter_to_model_params_array(
            model,
            fps,
            self._use_min_max_bounds,
            fit_param_indices=fit_param_indices,
        )
    
        if weights is None:
            value = np.ravel(model.evaluate(*inputs, *fps) - meas)
        else:
            value = np.ravel(weights * (model.evaluate(*inputs, *fps) - meas))
    
        if not np.all(np.isfinite(value)):
>           raise NonFiniteValueError(
                "Objective function has encountered a non-finite value, "
                "this will cause the fit to fail!\n"
                "This can be caused by non-finite values in the input data "
                "or weights, which can be removed with fit(..., "
                "filter_non_finite=True), or by diverging model parameters "
                "that yield non-finite model values."
            )
E           astropy.modeling.fitting.NonFiniteValueError: Objective function has encountered a non-finite value, this will cause the fit to fail!
E           This can be caused by non-finite values in the input data or weights, which can be removed with fit(..., filter_non_finite=True), or by diverging model parameters that yield non-finite model values.

..\..\.tox\py312-test-alldeps\Lib\site-packages\astropy\modeling\fitting.py:1177: NonFiniteValueError

(requires scipy)

I would assume the breaking change was in scipy 1.16.0, but we didn't catch via devdeps because it's also platform specific and only seems to affect windows.
Unfortunately this also means I don't have practical means to debug this easily (this problem doesn't reproduce on any machine I have at hand).
Marking this as a fire since it affects a required job and hence blocks all mergers.

Activity

  1. added this to the v7.1.1 milestone on Jun 23, 2025
  2. neutrinoceros commented on Jun 23, 2025

    @neutrinoceros
    ContributorAuthor

    With the Coordination Meeting coming up in a couple hours I assume we won't be able to immediately give this the attention that it requires, so I'm going to propose we just set a temporary pin for scipy, specifically on windows, so that other stuff is unblocked.

  3. neutrinoceros commented on Jun 23, 2025

    @neutrinoceros
    ContributorAuthor

    I just pushed the pin to #18331 because both problems are mutually blocking so the easiest way to unblock everything is to combine solutions into a single PR.

  4. pllim commented on Jun 23, 2025

    @pllim
    Member

    I think we can just move Sersic2D to here:

  5. neutrinoceros commented on Jun 23, 2025

    @neutrinoceros
    ContributorAuthor

    Isn't this another way to hide the problem, but less discoverable ? Does anyone understand why this warning wasn't raised before and now is ? and why it's only on windows ?

  6. pllim commented on Jun 23, 2025

    @pllim
    Member

    @WilliamJamieson maybe. But Sersic2D is already in the other ones.

  7. WilliamJamieson commented on Jun 24, 2025

    @WilliamJamieson
    Contributor

    Could we just skip this test on windows for now, and update this issue with a exact description of the failure?

  8. neutrinoceros commented on Jun 24, 2025

    @neutrinoceros
    ContributorAuthor

    skipping this specific test is perhaps a little bit too involved for a temporary patch, because it'd require unrolling a 2D parametrization matrix. We could easily skip the whole (parametrized) test instead but I'm not sure that's preferable to pinning scipy (maybe it is).
    I just added pytest's output to the description.

  9. pllim commented on Jul 2, 2025

    @pllim
    Member

    @neutrinoceros , does #18381 work for your setup?

  10. removed this from the v7.1.1 milestone on Sep 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions