4
import numpy as np
import astropy as ap

def mass(FWHM, lumi):
    abs_lumi = bhm.L_1450(lumi)
    s1 = (FWHM/1000)
    s2 = ((abs_lumi)/(10**44))
    s = [(s1**2)*(s2**0.53)]
    #mass = np.log10((s1**2)*(s2**0.53)) + 6.66 #old way, didn't work
    mass = np.log10(s) + 6.66
    return mass

I'm trying to use the numpy log10 function, but I keep getting an error that reads:

AttributeError: 'float' object has no attribute 'log10'

I tried putting my argument into a list (s variable), but I got the same error message. FWHM and lumi are both numbers with decimal points (I think they're called floating point numbers).

1
  • 3
    what is bhm? Why do you tag and import astropy? It's not used anywhere. What exactly is your input (make it reproduciple)? If I ignore the bhm.L_1450 call and just use lumi everything works fine with integers, floats and arrays. What numpy version are you using? Commented Nov 13, 2016 at 18:00

2 Answers 2

6

The answer to this is a bit tricky and requires a bit of knowledge how Python handles integers and how numpy coerces types. Thanks @ali_m for your comment!

Assuming 64 bit integer the biggest representable integer is 9,223,372,036,854,775,807 (see for example Wikipedia) which is roughly 10**19. But Python falls back to unlimited integer representations as soon as this value is exceeded (like in your case 10**44). But this unlimited precision type is not nativly supported by NumPy, so results will fall back to objects and these object arrays don't support all (any?) ufuncs, like np.log10.

The solution is simple: Convert this large number to a floating point number:

>>> # Negative powers will result in floats: 44 -> -44, * instead of /
>>> np.array([10, 20]) * 10**-44
array([  1.00000000e-43,   2.00000000e-43])

>>> # you could also make the base a float: 10 -> 10.
>>> np.array([10, 20]) / 10.**44
array([  1.00000000e-43,   2.00000000e-43])

>>> # or make the exponent a float: 44 -> 44.
>>> np.array([10, 20]) / 10**44.
array([  1.00000000e-43,   2.00000000e-43])

>>> # manually cast the result to a float
>>> np.array([10, 20]) / float(10**44)
array([  1.00000000e-43,   2.00000000e-43])

>>> # not working, result is an object array which cannot be used for np.log10
>>> np.array([10, 20]) / (10**(44))
array([1e-43, 2e-43], dtype=object)
>>> #                       ^---------that's the problem!

All you need is to change the third line in your function:

import numpy as np

def mass(FWHM, lumi):
    s1 = FWHM / 1000
    s2 = lumi * 10**-44   # changed line, using the first option.
    s = s1**2 * s2**0.53
    mass = np.log10(s) + 6.66
    return mass

This works at least with all my test inputs, for example:

>>> mass(np.array([10., 20]), np.array([10., 20]))
array([-20.13      , -19.36839411])
Sign up to request clarification or add additional context in comments.

1 Comment

I think the issue is related to the fact that (10**(44)) yields an integer that is too large to be represented by any of numpy's integer dtypes. np.array(10**44) is an np.object array, containing a native Python integer. np.iinfo(np.int64).max == 9223372036854775807, which is only about 10¹⁹. If the exponentiation is performed on floats rather than ints then you will get an np.float64 array instead - np.array(10.0**44.0).dtype == np.float64. Likewise, if the exponent is negative then you will, of course, get a float result.
2

The reason for the problem is as explained above. One simple solution is to convert the type of array using .astype().

any_np_array = []
any_np_array = any_np_array.astype(float)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.