Can not put the result of Bessel function into numpy's array - python

Following to this post:
How to put complex into a numpy's array?
It seems work well for me.
But why did i get this error in this case?
1 #!/usr/bin/env python
2 import scipy.special
3 import numpy as np
4
5 deg = 10
6 nodes = np.polynomial.legendre.leggauss(deg)[0]
7 A = np.zeros((deg, deg), dtype=complex)
8 for i in range(0, deg):
9 for j in range(0, deg):
10 A[i, j] = scipy.special.sph_yn(0, nodes[i]*nodes[j])[0]
machine:Desktop users$ ./aa.py
Traceback (most recent call last):
File "./aa.py", line 10, in <module>
A[i, j] = scipy.special.sph_yn(0, nodes[i]*nodes[j])[0]
TypeError: can't convert complex to float
Additional: What did i get from sph_yn if i comment line 10 and print scipy.special.sph_yn(0, nodes[i]*nodes[j])[0] out in nest for loop
[-0.61456112]
[-0.79004531]
[-1.19235662]
[-2.16125343]
[-6.82467416]
[ 6.82467416+0.j]
[ 2.16125343+0.j]
[ 1.19235662+0.j]
[ 0.79004531+0.j]
[ 0.61456112+0.j]
... and so on

special.sph_yn(0, nodes[i]*nodes[j])[0] returns a numpy array containing 1 element. You want to assign the value inside this array to A, not the array itself. To get the single value out of the array, use the item() method:
A[i, j] = special.sph_yn(0, nodes[i]*nodes[j])[0].item()
Note that using a list comprehension:
A = np.array([[special.sph_yn(0, nodes[i]*nodes[j])[0].item()
for j in range(deg)]
for i in range(deg) ])
would also work, and (if you have the memory) is faster than assigning values to a NumPy array one element at a time.

Related

Python ValueError when putting one array into another

I'm trying to insert one array into another, but I think I'm having a dimensioning issue with the arrays, leading to a ValueError. The exponential segment I'm trying to insert lives in EXP and prints as I'd expect, but running len() on it returns 1. Why would an array that prints with more than one element return a len() of 1? Code snippet below:
SPR = 48000 # Hz
duration = 0.2 # second
t = numpy.linspace(0, duration, duration * SPR)
p_list = [0, numpy.pi, 0]
SIGNALS = [(16000 * numpy.sin((2 * numpy.pi * t * 20) + p)).astype('int16')
for p in p_list]
EXP = [(16000 * (2**(-100*t))).astype('int16')]
e=EXP[0:4200]
print(e)
print(len(e))
SIGNALS[0][600:4800] = e
returns
[array([16000, 15976, 15953, ..., 0, 0, 0], dtype=int16)]
1
Traceback (most recent call last):
File "/home/pi/Experiments/actronika-exp.py", line 87, in <module>
SIGNALS[0][600:4800] = e
ValueError: setting an array element with a sequence.
The problem is that you are inserting the array inside a list when you do:
X = [np.array([0, ...])]
Thus X is a list with a array inside, I think you should just do:
X = np.array([0, ...])
However, if you need the array inside list thing, you should change this line
e=EXP[0:4200]
to
e=EXP[0][0:4200]
Now you are taking the first array, inside the list EXP.
[array([16000, 15976, 15953, ..., 0, 0, 0], dtype=int16)]
This (e) is a numpy array inside a python list. len(e) returns the list's length, which is 1, since it contains 1 element: the numpy array

An array of floats giving a numpy.ndarray object

This is a followup question from the one I posted a few minutes ago. The problem I was having with multiplying int with float is fixed, thanks to user2357112 in the comments. However, it's come across another roadblock.
Code:
from __future__ import division
from fractions import Fraction
import numpy as np
from numpy import linalg as LA
def gcd(m,n):
if m < n:
return gcd(n,m)
return gcd(n,m%n)
def lcm(m,n):
return (m*n)/(gcd(m,n))
def answer(m):
tbd = []
l = len(m)
for i in range(l):
s = sum(m[i])
if s == 0:
tbd.append(i)
m[i][i] = 1
else:
for j in range(l):
m[i][j] /= s
tbd.sort(reverse=True)
a = np.array(m)
r = np.diag([1.0 for x in range(l)])
for i in range(100):
r *= a
initial = [0 for x in range(l)]
initial[0] = 1
final = initial * r
for i in tbd:
del final[i]
dens = []
for i in range(len(final)):
final[i] = final[i].limit_denominator()
dens.append(final[i].denominator)
lc = dens[0]
for j in range(1,len(dens)):
lc = lcm(lc,dens[j])
for i in range(len(final)):
final[i] = int(final[i] * lc)
final.append(lc)
return final
def main():
print answer([[1,2],[2,1]])
print answer([[0,1,0,0,0,1],[4,0,0,3,2,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]])
main()
Code in ideone: http://ideone.com/DO1otS
Error:
Traceback (most recent call last):
File "prog.py", line 51, in <module>
File "prog.py", line 48, in main
File "prog.py", line 37, in answer
AttributeError: 'numpy.ndarray' object has no attribute 'limit_denominator'
I am confused about why final[i] was recognized as a numpy.ndarray object. I thought that, since final is a 1-dimensional array, final[i] will therefore return the value (a float) within that array at index i. I'm not sure why that is not the case. Thank you in advance!
This is the answer to your question "I am confused about why final[i] was recognized as a numpy.ndarray object." In the following snippet of code
r = np.diag([1.0 for x in range(l)])
initial = [0 for x in range(l)]
final = initial * r
I skipped non-essential code. The code above shows that r is a numpy.ndarray and initial is a list. Then final is a product of a numpy.ndarray and a list. The result of this product is a numpy.ndarray.
What is also important is that r is an array of floats. Therefore final is also an array of floats and not fraction objects. Therefore you cannot call limit_denominator() on elements of final.
In addition, code such as:
for i in tbd:
del final[i]
looks quite suspicious.

NumPy multiplying int with float seems to not work

I am working on Google's "Doomsday Fuel" problem in Python 2.7 (it needs to be done in Python 2.7, hence the from __future__ import division line) that uses NumPy, which admittedly I am not too familiar with.
The WIP code (with a lot of comments added for your convenience):
from __future__ import division
from fractions import Fraction
import numpy as np
from numpy import linalg as LA
def gcd(m,n):
'''
function for finding the greatest common divisor of m and n
used mostly for the LCM function
'''
if m < n:
return gcd(n,m)
return gcd(n,m%n)
def lcm(m,n):
'''
function for finding the least common multiple of m and n
using the fact that m*n = gcd(m,n)*lcm(m,n)
'''
return (m*n)/(gcd(m,n))
def answer(m):
'''
m is an square matrix of nonnegative integers
dimensions guaranteed to be at most 10x10
'''
tbd = [] #stands for To Be Deleted
l = len(m)
for i in range(l):
'''
Checks each row
If row i is empty, add i to tbd, then make m[i][i] = 1
Otherwise, divide row i by the sum of row i to "normalize" it
e.g. [[3,2],[0,0]] would become [[0.6,0.4],[0,1]]
'''
s = sum(m[i])
if s == 0:
tbd.append(i)
m[i][i] = 1
else:
for j in range(l):
m[i][j] /= s
tbd.sort(reverse=True)
a = np.array(m)
r = np.diag([1 for x in range(l)]) #set initial matrix r which is just the identity matrix with same dimensions as a
for i in range(100):
r *= a #with each row adding up to just 1, r should stay stable
initial = [0 for x in range(l)]
initial[0] = 1
final = initial * r
for i in tbd:
del final[i]
dens = [] #denominators
for i in range(len(final)):
final[i] = final[i].limit_denominator()
dens.append(final[i].denominator) #collect all denominators
lc = dens[0]
for j in range(1,len(dens)):
lc = lcm(lc,dens[j]) #find LCM of all the denominators
for i in range(len(final)):
final[i] = int(final[i] * lc) #multiply the final array (which uses Fractions) by the LCM, then convert elements to int
final.append(lc)
return final
def main():
print answer([[1,2],[2,1]])
print answer([[0,1,0,0,0,1],[4,0,0,3,2,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0],[0,0,0,0,0,0]])
main()
Code in Ideone: http://ideone.com/DO1otS
The error message:
Traceback (most recent call last):
File "prog.py", line 51, in <module>
File "prog.py", line 48, in main
File "prog.py", line 29, in answer
TypeError: Cannot cast ufunc multiply output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
Why can't the program multiply int and float together? Or is there another part in this error message that I'm missing?

Array is too big error in Python

I have this code in python:
from numpy import *
import itertools
m, n = 6, 10
set_m = [i + 1 for i in range(m + 1)]
comb = zeros(((m + 1) ** n, n), dtype=int)
k = 0
for i in itertools.product(set_m, repeat=n):
comb[k][:] = i
k += 1
But when I run it, I got this error:
Traceback (most recent call last):
File "main.py", line 33, in <module>
comb = zeros(((m + 1) ** n, n), dtype=int)
ValueError: array is too big.
If you are sure you MUST have a billion element array, and there is no way around it whatsoever (sometimes happens, but not every day), you can use memmap to create the array in the hard drive instead of the RAM memory. But I think it would be wise to search for ways to re-write your code to avoid doing such a slow thing.

Reading pixels in python: "ValueError too many values to unpack"

I want to read a .tif file and count the number of pixels in an image and determine the density of objects, but when I attempt this y, x = np.indices(image.shape) it gives me then
Value Error (ValueError: too many values to unpack, File "<stdin>", line 1, in <module>).
My code is as follows:
import sys
import os
import numpy as np
from pylab import *
import scipy
import matplotlib.pyplot as plt
import math
#Function
def radial_plot(image):
y, x = np.indices(image.shape) # <----- Problem here???
center = np.array([(x.max()-x.min())/2.0, (x.max()-x.min())/2.0])
r = np.hypot(x - center[0], y - center[1])
ind = np.argsort(r.flat)- center[1])
r_sorted = r.flat[ind]
i_sorted = image.flat[ind]
r_int = r_sorted.astype(int)
deltar = r_int[1:] - r_int[:-1]
rind = np.where(deltar)[0]
nr = rind[1:] - rind[:-1]
csim = np.cumsum(i_sorted, dtype=float)
tbin = csim[rind[1:]] - csim[rind[:-1]]
radial_prof = tbin / nr
return rad
#Main
img = plt.imread('dat.tif')
radial_plot(img)
The issue is that you are attempting to assign more than two values to only two varibles:
>>> a, b = range(2) #Assign two values to two variables
>>> a
0
>>> b
1
>>> a, b = range(3) #Attempt to assign three values to two variables
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
In Python 2.x you can do the following:
>>> a, b = range(3)[0], range(3)[1:]
>>> a
0
>>> b
[1, 2]
Just for completeness, if you had Python 3.x, you could do Extended Iterable Unpacking:
>>> a, *b, c = range(5)
>>> a
0
>>> c
4
>>> b
[1, 2, 3]
Hope this helps
np.indices returns an array representing the indices of the grid. The error basically indicates that there are more than 2 values obtained by calling the indices method. Since it's returning a grid, you can assign it to a variable such as grid and then access the indices accordingly.
The crux of the error is the function call returns more than just 2 values, and in your code you are trying to 'squeeze' them into just 2 variables.
For eg.
s = "this is a random string"
x, y = s.split()
The above code gives you a value error since there are 5 strings obtained by calling split(), while I am trying to accommodate them into just 2 variables.

Categories

Resources