[SciPy-User] idiom for iterators, expr(T) if isscalar(T) else array([expr(t) for t in T])

josef.pktd at gmail.com josef.pktd at gmail.com
Thu Oct 15 12:13:34 EDT 2009


On Thu, Oct 15, 2009 at 11:56 AM,  <josef.pktd at gmail.com> wrote:
> On Wed, Oct 14, 2009 at 1:23 PM, denis <denis-bz-gg at t-online.de> wrote:
>> On Oct 14, 2:02 pm, Yosef Meller <yosef... at post.tau.ac.il> wrote:
>>
>>> v_expr = numpy.vectorize(expr)
>>> v_expr(T)
>>>
>>> Is that what you wanted?
>>
>>
>> Yosef,
>>  thanks, the right direction -- there must be a numpy primitive for
>> this.
>> But 2 problems with vectorize:
>> 1) an optional arg => TypeError: __call__() got an unexpected keyword
>> argument 'h'
>> 2) vectorize => broadcasting => ValueError
>> Here's a test case: ugly, but funciter() is at least correct :)
>
>
> broadcasting is nice, two changes below and it produces an output
> without exception.
> I didn't check whether the output makes sense. I guess vectorize still
> needs to have compatible array dimension in its arguments for
> broadcasting. But in your function, vectorize doesn't seem necessary.
>
> Josef
>
>>
>>
>> """ funciter, vectorize ?  14oct """
>> import numpy as np
>>
>> def spline_2p2s( t, p0, p1, m0, m1, h=1 ):
>>    """ Hermite 2-point, 2-slope spline
>>        t: a scalar / range / iterator
>>        p0 p1 m0 m1: scalars or arrays
>>        Beware: t and p0 both vecs => broadcasting =>
>>            ValueError: shape mismatch: objects cannot be broadcast to
>> a single shape
>>        (need guidelines, axioms on broadcasting)
>>    """
>>    def f(t):
>>        t2 = t*t
>>        t3 = t2*t
>>        return (
>>              p0 * (2*t3 - 3*t2 + 1)
>>            + p1 * (-2*t3 + 3*t2)
>>            + m0 * h * (t3 - 2*t2 + t)
>>            + m1 * h * (t3 - t2) )
>
> change number 1
>
> -    return funciter( f, t )
> +   return f(t) #funciter( f, t )
>>
>> def funciter( f, T ):
>>    return f(T) if np.isscalar(T) \
>>        else np.array([ f(t) for t in T ])
>>
>> #...............................................................................
>> if __name__ == "__main__":
>
> change number two:
>
> -    t = np.arange( 0, 1.01, .1 )
> +   t = np.arange( 0, 1.01, .1 )[:,None]
>
>>    p0 = np.array(( 0, 0 ))
>>    p1 = np.array(( 1, 0 ))
>>    m0 = np.array(( 1, 1 ))
>>    m1 = np.array(( 1, -1 ))
>>
>>    s = spline_2p2s( t, p0, p1, m0, m1 )
>>    print "spline_2p2s", s.T
>>
>>    spline_2p2s_vec = np.vectorize( spline_2p2s )
>>    s = spline_2p2s_vec( t, p0, p1, m0, m1 )
>>    print "spline_2p2s_vec", s.T
>> _______________________________________________
>> SciPy-User mailing list
>> SciPy-User at scipy.org
>> http://mail.scipy.org/mailman/listinfo/scipy-user
>>
>

here's a minimum on broadcasting:

>>> p = np.array(( 1, -1 ))
>>> p.shape
(2,)
>>>
>>> t = np.arange(3)
>>> t.shape
(3,)
>>> t*p0
Traceback (most recent call last):
ValueError: shape mismatch: objects cannot be broadcast to a single shape


cannot multiply elementwise two arrays that have different length in
the same dimension

solution: add a new dimension, turn t into a "column vector"
then each (one element) row of `t` is multiplied with each (one
element) column of `p`

t[:,None] or t[:, np.newaxis] add a new axis and increase dimension of array

more explanation in docs


>>> np.atleast_2d(t).T
array([[0],
       [1],
       [2]])
>>> np.atleast_2d(t).T * p
array([[ 0,  0],
       [ 1, -1],
       [ 2, -2]])
>>> t[:,None].shape
(3, 1)
>>> t[:,None] * p
array([[ 0,  0],
       [ 1, -1],
       [ 2, -2]])

Josef



More information about the SciPy-User mailing list