yuzie007 / mpltern

Ternary plots as projections of Matplotlib
https://yuzie007.github.io/mpltern
MIT License
39 stars 2 forks source link

hexbin and tribin throwing an error related to a cast #15

Closed jonnyprouty closed 4 months ago

jonnyprouty commented 4 months ago

Hello, I am receiving the following error when attempting to use either hexbin() or tribin() via the following.

t,l,r is loaded from the attached csv: foobar.csv

roi_fig = plt.figure()
roi_ax = roi_fig.add_subplot(projection="ternary", ternary_sum=100.0)
roi_ax.scatter(t, l, r) 

image

But if I instead try to do either a hexbin() or a tribin()

roi_fig = plt.figure()
roi_ax = roi_fig.add_subplot(projection="ternary", ternary_sum=100.0)
roi_ax.hexbin(t, l, r, edgecolors="none")

I receive the following error

Traceback (most recent call last):
  File "/usr/lib64/python3.12/site-packages/matplotlib/cbook.py", line 298, in process
    func(*args, **kwargs)
  File "/usr/lib64/python3.12/site-packages/matplotlib/widgets.py", line 2358, in release
    self._release(event)
  File "/usr/lib64/python3.12/site-packages/matplotlib/widgets.py", line 3383, in _release
    self.onselect(self._eventpress, self._eventrelease)
  File "<ipython-input-111-131b3757f1b8>", line 37, in onselect
    roi_ax.hexbin(t, l, r, edgecolors="none")
  File "/home/foobar/.local/lib/python3.12/site-packages/mpltern/ternary/_axes.py", line 423, in hexbin
    t, l, r = _normalize_tlr(t, l, r, self.ternary_sum)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/foobar/.local/lib/python3.12/site-packages/mpltern/ternary/_axes.py", line 809, in _normalize_tlr
    t *= scale
numpy.core._exceptions._UFuncOutputCastingError: Cannot cast ufunc 'multiply' output from dtype('float64') to dtype('>u2') with casting rule 'same_kind'
In [112]: help mpltern.hexbin()

I did a bit of hunting to see if I could bypass the error, and found this: https://stackoverflow.com/questions/38673531/numpy-cannot-cast-ufunc-multiply-output-from-dtype

It looks like it will solve the issue, sadly I don't have the time at the moment to actually implement the fix. Hopefully this helps! Thanks for releasing mpltern, it's very useful!

jonnyprouty commented 4 months ago

As a work around, I am normalizing my data before calling hexbin(norm=None) or tribin(norm=None) and that allows me to plot my data successfully.

total = a = np.asarray([t,l,r]).sum(axis=0)
t = 100 * t / total
l = 100 * l / total
r = 100 * r / total
roi_ax.hexbin(t, l, r, edgecolors="none", norm=None)
yuzie007 commented 4 months ago

Hello @jonnyprouty thank you for using mpltern and reporting your issue.

As your error message says, the issue is that your t, l, r are recognized as unsigned integer, while your ternary_sum is in float. The most straightforward solution is to cast your t, l, r into float, as

t = np.asarray(t, float)
l = np.asarray(l, float)
r = np.asarray(r, float)

Actually when loaded using np.loadtxt, your values should be by default loaded as float. The following code therefore does not show the error.

import matplotlib.pyplot as plt
import mpltern
import numpy as np

# t, l, r = np.loadtxt("foobar.csv", delimiter=",", unpack=True, dtype=">u2")
t, l, r = np.loadtxt("foobar.csv", delimiter=",", unpack=True)

roi_fig = plt.figure()
roi_ax = roi_fig.add_subplot(projection="ternary", ternary_sum=100.0)
# roi_ax.scatter(t, l, r)
roi_ax.hexbin(t, l, r)

I however agree that, for better consistency within mpltern and with Matplotlib, the error message should be suppressed. I will fix this in the next bug-fix release.

BTW each row in your foobar.csv does not sum up to 100.0. Please be also sure if this is reasonable for your analysis.

yuzie007 commented 4 months ago

Just now mpltern 1.0.4 with the fix of the casting is published in PyPI. With this, I would like to close this issue. Thank you @jonnyprouty once again for your report and using mpltern!

jonnyprouty commented 4 months ago

Hello @yuzie007 , thanks for the quick response and update.

BTW each row in your foobar.csv does not sum up to 100.0. Please be also sure if this is reasonable for your analysis.

In this case it's ok, as the 3 datatypes are a subset of a larger dataset which sums to 100. Thanks for checking though!

ust now mpltern 1.0.4 with the fix of the casting is published in PyPI. With this, I would like to close this issue. Thank you @jonnyprouty once again for your report and using mpltern!

No problem at all! Thanks again.