I am using a Python module called emcee to sample a distribution. I need to pass a (37,100) (which I have named Ntrig and Nsamp, respectively) array called events to the below function.
def mp(SNR2, *events):
events = np.asarray(events).reshape((Ntrig,Nsamp))
bessel = special.iv(0,np.sqrt(x*SNR2(event)))
exp = np.exp(-0.5*(x+SNR2(event)))
I = integrate.quad(lambda x: exp*bessel,0,SNRth**2)[0]
return np.asarray([np.array[I for event in events[i]] for i in range(len(events))]).reshape(events.shape)
I keep getting the error:
ValueError: total size of new array must be unchanged
As I understand, *events will break up the events array into 37*100 separate arguments. Shouldn't the next line where I reshape the array just put it back into a 37 by 100 array?
P.S. before you ask why I even bother breaking up events into separate arguments--the module needs this to work, it can't take an array.
Full Traceback error:
ValueError Traceback (most recent call last)
<ipython-input-17-c8e815326a69> in <module>()
----> 1 mp(SNR2,events)
<ipython-input-16-9f73f234c628> in mp(SNR2, *events)
5 def mp(SNR2, *events):
6 events = np.asarray(events).reshape((Ntrig,Nsamp))
----> 7 return np.asarray([np.array([integrate.quad(lambda x: np.exp(-0.5*(x+SNR2(event)))*special.iv(0,np.sqrt(x*SNR2(event))),0,SNRth**2)[0] for event in events[i]]) for i in range(len(events))]).reshape(events.shape)
8 # return integrate.quad(lambda x: 0.5*np.exp(-0.5*(x+SNR2(event)))*special.iv(0,np.sqrt(x*SNR2(event))),0,SNRth**2)[0]
9 def pp(SNR2, *events):
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
279 args = (args,)
280 if (weight is None):
--> 281 retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
282 else:
283 retval = _quad_weight(func,a,b,args,full_output,epsabs,epsrel,limlst,limit,maxp1,weight,wvar,wopts)
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
343 if points is None:
344 if infbounds == 0:
--> 345 return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
346 else:
347 return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
<ipython-input-16-9f73f234c628> in <lambda>(x)
5 def mp(SNR2, *events):
6 events = np.asarray(events).reshape((Ntrig,Nsamp))
----> 7 return np.asarray([np.array([integrate.quad(lambda x: np.exp(-0.5*(x+SNR2(event)))*special.iv(0,np.sqrt(x*SNR2(event))),0,SNRth**2)[0] for event in events[i]]) for i in range(len(events))]).reshape(events.shape)
8 # return integrate.quad(lambda x: 0.5*np.exp(-0.5*(x+SNR2(event)))*special.iv(0,np.sqrt(x*SNR2(event))),0,SNRth**2)[0]
9 def pp(SNR2, *events):
<ipython-input-16-9f73f234c628> in SNR2(*events)
1 def SNR2(*events):
----> 2 events = np.asarray(events).reshape((Ntrig,Nsamp))
3 C = 5*np.pi**(-1.33333)*events**(1.66667)/(96*d**2)
4 return C*integrate.quad(lambda f: f**(-2.3333)/S(f), 20, 1500, limit=1000)[0]
5 def mp(SNR2, *events):
ValueError: total size of new array must be unchanged
As I understand,
eventswill break up the events array into 37*100 separate arguments.
This is not true. If you call mp using
mp(SNR2, events)
then inside mp, events will be a 1-element tuple, (arr,), where arr is the (37, 100)-shaped array.
If you call mp using
mp(SNR2, *events)
then inside mp, events will be a 37-element tuple, where the 37 elements are the 37 rows of the (37, 100)-shaped array.
If you call mp using
mp(SNR2, *events.flat)
then inside mp, events will be a tuple of 37*100 elements.
Notice that the last stanza of the traceback says:
<ipython-input-16-9f73f234c628> in SNR2(*events)
1 def SNR2(*events):
----> 2 events = np.asarray(events).reshape((Ntrig,Nsamp))
3 C = 5*np.pi**(-1.33333)*events**(1.66667)/(96*d**2)
4 return C*integrate.quad(lambda f: f**(-2.3333)/S(f), 20, 1500, limit=1000)[0]
5 def mp(SNR2, *events):
ValueError: total size of new array must be unchanged
So the error is raised while Python is in the SNR2 function.
Since SNR2 was called in mp using SNR2(event), and event is a (37,100)-shaped array, the event variable in SNR2 is a 1-element tuple containing the original array. That's not what you want.
The easiest way to fix the code is to define
def SNR2(events):
# no longer needed
# events = np.asarray(events).reshape((Ntrig,Nsamp))
and just pass events around as one would expect.
However, if you can not change the signature of SNR2, then you must call it with
SNR2(*event.flat)
inside the mp function.
Reference: Here is an excellent explanation of the * unpacking operator, and how the syntax is used when defining functions, and calling functions.