Repository: proplot-dev/proplot
Issue: `imshow` fails to plot boolean arrays

<!-- Thanks for helping us make proplot a better package! If this is a bug report, please use the template provided below. If this is a feature request, you can delete the template text (just try to be descriptive with your request). -->

### Description

`imshow` errors due to `np.sign` being applied to a boolean.

### Steps to reproduce

A "[Minimal, Complete and Verifiable Example](http://matthewrocklin.com/blog/work/2018/02/28/minimal-bug-reports)" will make it much easier for maintainers to help you.

```python
import proplot as pplt
import numpy as np
fig, ax = pplt.subplots()
ax.imshow(np.random.rand(5, 5).astype(bool))
```

**Expected behavior**: [What you expected to happen]

**Actual behavior**: [What actually happened]


```python traceback
---------------------------------------------------------------------------
UFuncTypeError                            Traceback (most recent call last)
Cell In[9], line 2
      1 fig, ax = pplt.subplots()
----> 2 ax.imshow(np.random.rand(5, 5).astype(bool))

File /u/aurora-r0/staniewi/repos/proplot/proplot/internals/inputs.py:292, in _preprocess_or_redirect.<locals>._decorator.<locals>._preprocess_or_redirect(self, *args, **kwargs)
    289             ureg.setup_matplotlib(True)
    291 # Call main function
--> 292 return func(self, *args, **kwargs)

File /u/aurora-r0/staniewi/repos/proplot/proplot/axes/plot.py:4150, in PlotAxes.imshow(self, z, **kwargs)
   4146 """
   4147 %(plot.imshow)s
   4148 """
   4149 kw = kwargs.copy()
-> 4150 kw = self._parse_cmap(z, default_discrete=False, **kw)
   4151 guide_kw = _pop_params(kw, self._update_guide)
   4152 m = self._call_native('imshow', z, **kw)

File /u/aurora-r0/staniewi/repos/proplot/proplot/internals/warnings.py:110, in _rename_kwargs.<locals>._decorator.<locals>._deprecate_kwargs_wrapper(*args, **kwargs)
    105         key_new = key_new.format(value)
    106     _warn_proplot(
    107         f'Keyword {key_old!r} was deprecated in version {version} and may '
    108         f'be removed in {_next_release()}. Please use {key_new!r} instead.'
    109     )
--> 110 return func_orig(*args, **kwargs)

File /u/aurora-r0/staniewi/repos/proplot/proplot/axes/plot.py:2230, in PlotAxes._parse_cmap(self, cmap, cmap_kw, c, color, colors, norm, norm_kw, extend, vmin, vmax, vcenter, discrete, default_discrete, default_cmap, skip_autolev, min_levels, plot_lines, plot_contours, *args, **kwargs)
   2226     vmin, vmax, kwargs = self._parse_level_lim(
   2227         *args, vmin=vmin, vmax=vmax, **kwargs
   2228     )
   2229     if autodiverging and vmin is not None and vmax is not None:
-> 2230         if abs(np.sign(vmax) - np.sign(vmin)) == 2:
   2231             isdiverging = True
   2232 if discrete:

UFuncTypeError: ufunc 'sign' did not contain a loop with signature matching types <class 'numpy.dtype[bool_]'> -> None
```

### Equivalent steps in matplotlib


```python
# your code here, if applicable
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
ax.imshow(np.random.rand(5, 5).astype(bool))
```

### Proplot version

Paste the results of `import matplotlib; print(matplotlib.__version__); import proplot; print(proplot.version)` here.

```
>>> import matplotlib; print(matplotlib.__version__); import proplot; print(proplot.version)
3.4.3
0.0.post4012
```
(I just forked the latest. Seems like the tags aren't visible, so setuptools_scm doesn't like it)

Changed files:
proplot/internals/inputs.py

diff --git a/proplot/internals/inputs.py b/proplot/internals/inputs.py
index 2a7a2ec0..a55d6e26 100644
--- a/proplot/internals/inputs.py
+++ b/proplot/internals/inputs.py
@@ -130,6 +130,8 @@ def _to_numpy_array(data, strip_units=False):
         data = data.data  # support pint quantities that get unit-stripped later
     elif isinstance(data, (DataFrame, Series, Index)):
         data = data.values
+    if data.dtype == bool:
+        data = data.view(np.uint8)
     if Quantity is not ndarray and isinstance(data, Quantity):
         if strip_units:
             return np.atleast_1d(data.magnitude)