brian-team/brian2

Incompatible with numpy version >= 1.20 due to deprecated aliases

tim-ufer opened this issue · 5 comments

Writing simple lines like 20*volt result in a hard error due to the np.float alias being deprecated. Here's the corresponding error message:

AttributeError: module 'numpy' has no attribute 'float'.
`np.float` was a deprecated alias for the builtin `float`. To avoid this error in existing code, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
    https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations

As suggested in the message, this should be easy to fix by using builtin type keywords instead of old numpy aliases. Until then, users must install numpy version 1.19.5 or older to avoid such errors.

Hi @tim-ufer. Thanks for the report, but I think we fixed this about 2 years ago with #1273. With which version of Brian are you seeing this issue?

I have brian==2.5.1 installed via pip. Having numpy versions >= 1.20 causes the aforementioned errors. This has happened on multiple machines if that's relevant

Here's the full traceback. Looks like there's at least one use of np.float left in units/fundamentalunits.py:1600 but when checking the file in question on master, it's just float. So I suppose the actual question is why older versions of this file are ending up in the 2.5.1 pypi distribution?

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~\.envs\py_snn\lib\site-packages\IPython\core\formatters.py:342, in BaseFormatter.__call__(self, obj)
    340     method = get_real_method(obj, self.print_method)
    341     if method is not None:
--> 342         return method()
    343     return None
    344 else:

File ~\.envs\py_snn\lib\site-packages\brian2\units\fundamentalunits.py:1629, in Quantity._repr_latex_(self)
   1628 def _repr_latex_(self):
-> 1629     return f"${latex(self)}$"

File ~\.envs\py_snn\lib\site-packages\sympy\printing\printer.py:372, in _PrintFunction.__call__(self, *args, **kwargs)
    371 def __call__(self, *args, **kwargs):
--> 372     return self.__wrapped__(*args, **kwargs)

File ~\.envs\py_snn\lib\site-packages\sympy\printing\latex.py:3140, in latex(expr, **settings)
   2928 @print_function(LatexPrinter)
   2929 def latex(expr, **settings):
   2930     r"""Convert the given expression to LaTeX string representation.
   2931 
   2932     Parameters
   (...)
   3138 
   3139     """
-> 3140     return LatexPrinter(settings).doprint(expr)

File ~\.envs\py_snn\lib\site-packages\sympy\printing\latex.py:264, in LatexPrinter.doprint(self, expr)
    263 def doprint(self, expr) -> str:
--> 264     tex = Printer.doprint(self, expr)
    266     if self._settings['mode'] == 'plain':
    267         return tex

File ~\.envs\py_snn\lib\site-packages\sympy\printing\printer.py:292, in Printer.doprint(self, expr)
    290 def doprint(self, expr):
    291     """Returns printer's representation for expr (as a string)"""
--> 292     return self._str(self._print(expr))

File ~\.envs\py_snn\lib\site-packages\sympy\printing\printer.py:309, in Printer._print(self, expr, **kwargs)
    303 try:
    304     # If the printer defines a name for a printing method
    305     # (Printer.printmethod) and the object knows for itself how it
    306     # should be printed, use that method.
    307     if (self.printmethod and hasattr(expr, self.printmethod)
    308             and not isinstance(expr, BasicMeta)):
--> 309         return getattr(expr, self.printmethod)(self, **kwargs)
    311     # See if the class of expr is known, or if one of its super
    312     # classes is known, and use that print function
    313     # Exception: ignore the subclasses of Undefined, so that, e.g.,
    314     # Function('gamma') does not get dispatched to _print_gamma
    315     classes = type(expr).__mro__

File ~\.envs\py_snn\lib\site-packages\brian2\units\fundamentalunits.py:1600, in Quantity._latex(self, expr)
   1598 threshold = np.get_printoptions()['threshold'] // 100
   1599 if unitless.ndim == 0:
-> 1600     sympy_quantity = np.float(unitless)
   1601 elif unitless.ndim == 1:
   1602     array_str = np.array2string(unitless, separator=" & ", threshold=threshold,
   1603                                 max_line_width=sys.maxsize)

File ~\.envs\py_snn\lib\site-packages\numpy\__init__.py:305, in __getattr__(attr)
    300     warnings.warn(
    301         f"In the future `np.{attr}` will be defined as the "
    302         "corresponding NumPy scalar.", FutureWarning, stacklevel=2)
    304 if attr in __former_attrs__:
--> 305     raise AttributeError(__former_attrs__[attr])
    307 # Importing Tester requires importing all of UnitTest which is not a
    308 # cheap import Since it is mainly used in test suits, we lazy import it
    309 # here to save on the order of 10 ms of import time for most users
    310 #
    311 # The previous way Tester was imported also had a side effect of adding
    312 # the full `numpy.testing` namespace
    313 if attr == 'testing':

Upon further inspection, I noticed that the file in question (fundamentalunits.py) was not updated in pull request #1273 but in another commit of yours last October. This fix is visible on master but for some reason it is not part of the pypi distribution. For now I've simply changed that single line from np.float to float locally (it seems to have been the only faulty leftover) and I no longer get errors for code like 20*volt

Hi again, and sorry for the confusion. I misread your initial post a bit, and thought you ran into this issue with general code, just by using 20*volt somewhere. If you used a version from before the fixes in #1273, this would have been indeed the case, errors related to the aliases would pop up in many places. You are right that there is one place that I only fixed recently (and we did not yet have a release since that fix). This only concerns the LaTeX output you get in a jupyter notebook when you directly ask it to represent a Brian Quantity instead of e.g. printing it with print.

I hope I'll get around making a new release in the coming weeks, but until then there are also a few workarounds that you can use (apart from fixing the bug directly in the code as you did):

  • Do not ask for a representation of quantities, e.g. replace 20 * volt by print(20 * volt).
  • Remove the LaTeX formatting for quantities by stating del Quantity._repr_latex_ at the beginning of your session
  • Use a numpy version < 1.24

Note that you only get an error with numpy versions >= 1.24 (released in December last year), in versions >=1.20<1.24 you will only get a warning.

Hope that makes things a bit clearer!