python - 使用 mpmath 绘图时,Matplotlib 因 `TypeError` 失败
问题描述
我有非常小(有序e-500
)的 2D 数据,所以我不能使用我想绘制为 pcolormesh 的 numpy。例如,
import mpmath as mp
import matplotlib.pyplot as plt
import numpy as np
from mpmath import e as e
from mpmath import mpf, mpc,mp
mp.dps = 1000
y, x = np.meshgrid(np.linspace(-5, 5, 1000), np.linspace(-5, 5, 1000))
z = e ** (-x**2 + y)
z = z[:-1, :-1]
z_min, z_max = -np.abs(z).max(), np.abs(z).max()
编译得很好但是当我想做一些pcolormesh
事情时:
fig, ax = plt.subplots()
c = ax.pcolormesh(x, y, z, cmap='RdBu', vmin=z_min, vmax=z_max)
ax.set_title('Titles are overall a positive feature')
ax.axis([x.min(), x.max(), y.min(), y.max()])
fig.colorbar(c, ax=ax)
plt.show()
给出错误TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
为什么会这样?你知道如何解决这个问题吗?也许没有 mpmath 的绘图会有所帮助。
编辑:完整追溯
TypeError Traceback (most recent call last)
~/.local/lib/python3.8/site-packages/IPython/core/formatters.py in __call__(self, obj)
339 pass
340 else:
--> 341 return printer(obj)
342 # Finally look for special method names
343 method = get_real_method(obj, self.print_method)
~/.local/lib/python3.8/site-packages/IPython/core/pylabtools.py in <lambda>(fig)
246
247 if 'png' in formats:
--> 248 png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
249 if 'retina' in formats or 'png2x' in formats:
250 png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))
~/.local/lib/python3.8/site-packages/IPython/core/pylabtools.py in print_figure(fig, fmt, bbox_inches, **kwargs)
130 FigureCanvasBase(fig)
131
--> 132 fig.canvas.print_figure(bytes_io, **kw)
133 data = bytes_io.getvalue()
134 if fmt == 'svg':
~/.local/lib/python3.8/site-packages/matplotlib/backend_bases.py in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, bbox_inches, **kwargs)
2077 print_method, dpi=dpi, orientation=orientation),
2078 draw_disabled=True)
-> 2079 self.figure.draw(renderer)
2080 bbox_artists = kwargs.pop("bbox_extra_artists", None)
2081 bbox_inches = self.figure.get_tightbbox(renderer,
~/.local/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
36 renderer.start_filter()
37
---> 38 return draw(artist, renderer, *args, **kwargs)
39 finally:
40 if artist.get_agg_filter() is not None:
~/.local/lib/python3.8/site-packages/matplotlib/figure.py in draw(self, renderer)
1733
1734 self.patch.draw(renderer)
-> 1735 mimage._draw_list_compositing_images(
1736 renderer, self, artists, self.suppressComposite)
1737
~/.local/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
135 if not_composite or not has_images:
136 for a in artists:
--> 137 a.draw(renderer)
138 else:
139 # Composite any adjacent images together
~/.local/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
36 renderer.start_filter()
37
---> 38 return draw(artist, renderer, *args, **kwargs)
39 finally:
40 if artist.get_agg_filter() is not None:
~/.local/lib/python3.8/site-packages/matplotlib/axes/_base.py in draw(self, renderer, inframe)
2628 renderer.stop_rasterizing()
2629
-> 2630 mimage._draw_list_compositing_images(renderer, self, artists)
2631
2632 renderer.close_group('axes')
~/.local/lib/python3.8/site-packages/matplotlib/image.py in _draw_list_compositing_images(renderer, parent, artists, suppress_composite)
135 if not_composite or not has_images:
136 for a in artists:
--> 137 a.draw(renderer)
138 else:
139 # Composite any adjacent images together
~/.local/lib/python3.8/site-packages/matplotlib/artist.py in draw_wrapper(artist, renderer, *args, **kwargs)
36 renderer.start_filter()
37
---> 38 return draw(artist, renderer, *args, **kwargs)
39 finally:
40 if artist.get_agg_filter() is not None:
~/.local/lib/python3.8/site-packages/matplotlib/collections.py in draw(self, renderer)
2045 offsets = np.column_stack([xs, ys])
2046
-> 2047 self.update_scalarmappable()
2048
2049 if not transform.is_affine:
~/.local/lib/python3.8/site-packages/matplotlib/collections.py in update_scalarmappable(self)
790 return
791 if self._is_filled:
--> 792 self._facecolors = self.to_rgba(self._A, self._alpha)
793 elif self._is_stroked:
794 self._edgecolors = self.to_rgba(self._A, self._alpha)
~/.local/lib/python3.8/site-packages/matplotlib/cm.py in to_rgba(self, x, alpha, bytes, norm)
243 if norm:
244 x = self.norm(x)
--> 245 rgba = self.cmap(x, alpha=alpha, bytes=bytes)
246 return rgba
247
~/.local/lib/python3.8/site-packages/matplotlib/colors.py in __call__(self, X, alpha, bytes)
559 if np.ma.is_masked(X):
560 mask_bad = X.mask
--> 561 elif np.any(np.isnan(X)):
562 # mask nan's
563 mask_bad = np.isnan(X)
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
<Figure size 432x288 with 2 Axes> ```
解决方案
使用您的代码,编辑以在合理的测试时间内运行:
...: mp.dps = 10
...: y, x = np.meshgrid(np.linspace(-5, 5, 10), np.linspace(-5, 5, 10))
...: z = e ** (-x**2 + y)
...: z = z[:-1, :-1]
...: z_min, z_max = -np.abs(z).max(), np.abs(z).max()
...:
In [11]: z
Out[11]:
array([[mpf('9.357622969874e-14'), mpf('2.842594865759e-13'),
mpf('8.635040754285e-13'), mpf('2.623093769921e-12'),
mpf('7.968255300282e-12'), mpf('2.420542233701e-11'),
mpf('7.352958062098e-11'), mpf('2.233631436379e-10'),
mpf('6.785173193566e-10')],
...., dtype=object)
In [12]: z.dtype
Out[12]: dtype('O')
In [13]: np.isnan(z)
Traceback (most recent call last):
File "<ipython-input-13-72670087bbfa>", line 1, in <module>
np.isnan(z)
TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
通过使用mpmath
,您创建了一个对象 dtype 数组。虽然这可能具有更高的精度,但它的运行速度也慢得多,在某些情况下根本不运行。
isnan
需要一个数字 dtype 数组:
In [16]: np.any(np.isnan(z.astype(float)))
Out[16]: False
回溯表明在图中plot
使用isnan
“空白”nan
值。
这有效:
plt.pcolormesh(x, y, z.astype('float128'), cmap='RdBu', vmin=z_min, vmax=z_max)