Trying to Fix a Numpy Asscalar Deprecation Issue
While Trying to Update an Old Python Script I Ran into the Following Error: Module 'Numpy' Has No Attribute 'Asscalar'. Did You Mean: 'Isscalar'? Specifically...
While trying to update an old Python script I ran into the following error:
module 'numpy' has no attribute 'asscalar'. Did you mean: 'isscalar'?
Specifically:
def calibrate(x, y, z):
# H = numpy.array([x, y, z, -y**2, -z**2, numpy.ones([len(x), 1])])
H = numpy.array([x, y, z, -y**2, -z**2, numpy.ones([len(x)])])
H = numpy.transpose(H)
w = x**2
(X, residues, rank, shape) = linalg.lstsq(H, w)
OSx = X[0] / 2
OSy = X[1] / (2 * X[3])
OSz = X[2] / (2 * X[4])
A = X[5] + OSx**2 + X[3] * OSy**2 + X[4] * OSz**2
B = A / X[3]
C = A / X[4]
SCx = numpy.sqrt(A)
SCy = numpy.sqrt(B)
SCz = numpy.sqrt(C)
# type conversion from numpy.float64 to standard python floats
offsets = [OSx, OSy, OSz]
scale = [SCx, SCy, SCz]
offsets = map(numpy.asscalar, offsets)
scale = map(numpy.asscalar, scale)
return (offsets, scale)
I found that asscalar has been deprecated since NumPy 1.16. I found one reference that said to use numpy.ndarray.item, but I have no clue how to do that.
I did try this:
offsets = map.item(offsets)
scale = map.item( scale)
but got this error:
AttributeError: type object 'map' has no attribute 'item'
How can I solve this?
3 Answers
Temporary fix, worked in my case
import numpy
def patch_asscalar(a):
return a.item()
setattr(numpy, "asscalar", patch_asscalar)
Just replace numpy.scalar using numpy.ndarray.item, that is, change
offsets = map(numpy.asscalar, offsets)
scale = map(numpy.asscalar, scale)
to
offsets = map(numpy.ndarray.item, offsets)
scale = map(numpy.ndarray.item, scale)
Assuming X is a 1d array with shape (6,), I created a dummy sample, and applied your calculations (thorough the first offsets)
X = np.array([1, 2.3, 3.2, .4,5.2, 3])
and got two lists of numpy scalars.
In [58]: offsets
Out[58]: [0.5, 2.8749999999999996, 0.3076923076923077]
In [59]: type(offsets[0])
Out[59]: numpy.float64
Looks like the map lines are Python 2, intended to produce lists of regular python floats. Python 3 would use list(map(...)).
item is a method of numpy scalars (and single item arrays). It could be used as:
In [60]: [OSx.item(), OSy.item(), OSz.item()]
Out[60]: [0.5, 2.8749999999999996, 0.3076923076923077]
In [61]: [i.item() for i in offsets]
Out[61]: [0.5, 2.8749999999999996, 0.3076923076923077]
One applies it to the OS values before they are collected in a list, the other uses a list comprehension (which is easier to use than map, at least for this).
Same for scale.
But for scale we don't need to take the sqrt individually; just make an array from the 3 values, apply sqrt to the whole array. Then use tolist() method to create a list of python floats. That's better than trying to do sqrt and item individually.
In [63]: np.sqrt(np.array([A,B,C]))
Out[63]: array([2.65491199, 4.19778444, 1.16425593])
In [64]: np.sqrt(np.array([A,B,C])).tolist()
Out[64]: [2.6549119933262744, 4.197784443104389, 1.1642559271506094]