dynamicslab / pysindy

A package for the sparse identification of nonlinear dynamical systems from data
https://pysindy.readthedocs.io/en/latest/
Other
1.36k stars 304 forks source link

[BUG] AxesArray `ravel()` needed for some plotting functions. #480

Closed Jacob-Stevens-Haas closed 4 months ago

Jacob-Stevens-Haas commented 4 months ago

Currently, AxesArray tries to implement the most commonly used numpy functions that preserve certain axis information. For others, the numpy function executes and then calls AxesArray.__array_finalize__(self, obj), which tries to guess how to assign axes. This causes an error in ravel(), called by some plotting functions.

Reproducing code example:

import pysindy
import pysindy as ps
import numpy as np
from matplotlib import pyplot as plt

arr = ps.AxesArray(np.arange(5), {"ax_1": 0})
plt.scatter(arr, arr)

Error message:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/jake/github/pysindy/env/lib/python3.10/site-packages/matplotlib/pyplot.py", line 3684, in scatter
    __ret = gca().scatter(
  File "/home/jake/github/pysindy/env/lib/python3.10/site-packages/matplotlib/__init__.py", line 1465, in inner
    return func(ax, *map(sanitize_sequence, args), **kwargs)
  File "/home/jake/github/pysindy/env/lib/python3.10/site-packages/matplotlib/axes/_axes.py", line 4649, in scatter
    x = np.ma.ravel(x)
  File "/home/jake/github/pysindy/env/lib/python3.10/site-packages/numpy/ma/core.py", line 6882, in __call__
    return method(marr, *args, **params)
  File "/home/jake/github/pysindy/env/lib/python3.10/site-packages/numpy/ma/core.py", line 4677, in ravel
    r = ndarray.ravel(self._data, order=order).view(type(self))
  File "/home/jake/github/pysindy/pysindy/utils/axes.py", line 353, in __array_finalize__
    self._ax_map = _AxisMapping(obj.axes, obj.ndim)
  File "/home/jake/github/pysindy/pysindy/utils/axes.py", line 305, in __getattr__
    raise AttributeError(f"'{type(self)}' object has no attribute '{name}'")
AttributeError: '<class 'pysindy.utils.axes.AxesArray'>' object has no attribute 'axes'

PySINDy/Python version information:

current master, a0e36ddb08080ebbf2aeff47b7bae3e51ff8bc2a

Jacob-Stevens-Haas commented 4 months ago

Deep underneath, scatter is making a np.MaskedArray. This is losing the .axes property, as well as (sometimes) the _ax_map. See numpy.ma.core:MaskedArray.__array_finalize__. Also numpy.ma.core:asanyarray.