[Numpy-discussion] Vectorize or rewrite function to work with array inputs?

DParker at chromalloy.com DParker at chromalloy.com
Tue Feb 1 17:15:17 EST 2011

```I tested with mixed scalar and array inputs for t and far, and same size
arrays for both. I did not test with improperly sized arrays but I would
expect (desire) an exception to be raised when the arrays are not

Still the code seems like an ugly hack...

David Parker
Chromalloy - TDAG

From:   josef.pktd at gmail.com
To:     Discussion of Numerical Python <numpy-discussion at scipy.org>
Date:   02/01/2011 04:39 PM
Subject:        Re: [Numpy-discussion] Vectorize or rewrite function to
work with array inputs?
Sent by:        numpy-discussion-bounces at scipy.org

On Tue, Feb 1, 2011 at 3:20 PM,  <DParker at chromalloy.com> wrote:
> I'm not sure I need to dive into cython or C for this - performance is
not
> an issue for my problem - I just want a flexible function that will
accept
> scalars or arrays.
>
> Both Sebastian's and eat's suggestions show using indexing to handle the
> conditional statements in the original function. The problem I'm having
> implementing this is in getting the input arguments and outputs to a
common
> array size. Here's how I can do this but it seems ugly:
>
> # t and far are function arguments which may be scalars or arrays
> # ag is the output array
> # need to make everything array with common length
> t = np.array(t, ndmin=1)        # Convert t to an array
> far = np.array(far, ndmin=1)        # Convert far to an array
> ag = t*far*np.nan                        # Make an output array of the
> proper length using broadcasting rules
> t = np.zeros_like(ag)+t                # Expand t to the length of the
> output array
> far = np.zeros_like(ag)+far        # Expand far to the length of the
output
> array
>
> Now with all arrays the same length I can use indexing with logical
> statements:
> ag[far<0.005] = -3.472487e-22 * t ** 6. + 6.218811e-18 * t ** 5. -
> 4.428098e-14 * t ** 4. + \
>                 1.569889e-10 * t ** 3. - 0.0000002753524 * t ** 2. +
> 0.0001684666 * t + 1.368652

Does this work? Shouldn't this raise an exception ?

>>> x.shape
(5, 4)
>>> y.shape
(5, 4)
>>> x[y<10] = y
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
x[y<10] = y
ValueError: array is not broadcastable to correct shape

>
> The resulting code looks like this:
> import numpy as np
>
> def air_gamma_dp(t, far=0.0):
>     """
>     Specific heat ratio (gamma) of Air/JP8
>     t - static temperature, Rankine
>     [far] - fuel air ratio [- defaults to 0.0 (dry air)]
>     air_gamma - specific heat ratio
>     """
>     t = np.array(t, ndmin=1)
>     far = np.array(far, ndmin=1)
>     ag = t*far*np.nan
>     t = np.zeros_like(ag)+t
>     far = np.zeros_like(ag)+far
>
>     far[(far<0.) | (far>0.069)] = np.nan
>     t[(t < 379.) | (t > 4731.)] = np.nan
>     ag[(far<0.005)] = -3.472487e-22 * t ** 6. + 6.218811e-18 * t ** 5. -
> 4.428098e-14 * t ** 4. +
>                        1.569889e-10 * t ** 3. - 0.0000002753524 * t **
2. +
> 0.0001684666 * t + 1.368652
>     t[(t < 699.) | (t > 4731.)] = np.nan
>     a6 = 4.114808e-20 * far ** 3. - 1.644588e-20 * far ** 2. +
3.103507e-21
> * far - 3.391308e-22
>     a5 = -6.819015e-16 * far ** 3. + 2.773945e-16 * far ** 2. -
5.469399e-17
> * far + 6.058125e-18
>     a4 = 4.684637e-12 * far ** 3. - 1.887227e-12 * far ** 2. +
3.865306e-13
> * far - 4.302534e-14
>     a3 = -0.00000001700602 * far ** 3. + 0.000000006593809 * far ** 2. -
> 0.000000001392629 * far + 1.520583e-10
>     a2 = 0.00003431136 * far ** 3. - 0.00001248285 * far ** 2. +
> 0.000002688007 * far - 0.0000002651616
>     a1 = -0.03792449 * far ** 3. + 0.01261025 * far ** 2. - 0.002676877
*
> far + 0.0001580424
>     a0 = 13.65379 * far ** 3. - 3.311225 * far ** 2. + 0.3573201 * far +
> 1.372714
>     ag[far>=0.005] = a6 * t ** 6. + a5 * t ** 5. + a4 * t ** 4. + a3 * t
**
> 3. + a2 * t ** 2. + a1 * t + a0
>     return ag
>
> I was hoping there was a more elegant way to do this.

I think delaying the broadcasting to before the assignment to ag might
be better. Since your expressions are either in far or in t, delaying
and only broad cast before the assignment

maybe something like this with t that is not broadcasted

cond = (far<0.005)*((t < 379.) | (t > 4731.))
ag[cond] = (np.zeros(ag.shape) + (-3.472487e-22 * t ** 6. +
6.218811e-18 * t ** 5. -
> 4.428098e-14 * t ** 4. +
>                        1.569889e-10 * t ** 3. - 0.0000002753524 * t **
2. +
> 0.0001684666 * t + 1.368652))[cond]

Josef

>
> David Parker
> Chromalloy - TDAG
>
>
>
> From:        John Salvatier <jsalvati at u.washington.edu>
> To:        Discussion of Numerical Python <numpy-discussion at scipy.org>
> Date:        02/01/2011 02:29 PM
> Subject:        Re: [Numpy-discussion] Vectorize or rewrite function to
work
> with array inputs?
> Sent by:        numpy-discussion-bounces at scipy.org
> ________________________________
>
>
> Have you thought about using cython to work with the numpy C-API
> (http://wiki.cython.org/tutorials/numpy#UsingtheNumpyCAPI)? This will be
> fast, simple (you can mix and match Python and Cython).
>
> As for your specific issue: you can simply cast to all the inputs to
numpy
> arrays (using
> asarray
http://docs.scipy.org/doc/numpy/reference/generated/numpy.asarray.html)
> to deal with scalars. This will make sure they get broadcast correctly.
>
> On Tue, Feb 1, 2011 at 11:22 AM, <DParker at chromalloy.com> wrote:
>
> Using Sebastian's advice I was able to write a version that worked when
the
> input arguments are both arrays with the same length. The code provided
by
> eat works when t is an array, but not for an array of far.
>
> The numpy.vectorize version works with any combination of scalar or
array
> input. I still haven't figured out how to rewrite my function to be as
> flexible as the numpy.vectorize version at accepting either scalars or
array
> inputs and properly broadcasting the scalar arguments to the array
> arguments.
>
> David Parker
> Chromalloy - TDAG
>
>
>
> From:        eat <e.antero.tammi at gmail.com>
> To:        Discussion of Numerical Python <numpy-discussion at scipy.org>
> Date:        01/31/2011 11:37 AM
> Subject:        Re: [Numpy-discussion] Vectorize or rewrite function to
work
> with array inputs?
> Sent by:        numpy-discussion-bounces at scipy.org
> ________________________________
>
>
>
> Hi,
>
> On Mon, Jan 31, 2011 at 5:15 PM, <DParker at chromalloy.com> wrote:
> I have several functions like the example below that I would like to
make
> compatible with array inputs. The problem is the conditional statements
give
> a ValueError: The truth value of an array with more than one element is
> ambiguous. Use a.any() or a.all(). I can use numpy.vectorize, but if
> possible I'd prefer to rewrite the function. Does anyone have any advice
the
> best way to modify the code to accept array inputs? Thanks in advance
for
> any assistance.
>
> If I understod your question correctly, then air_gamma could be coded
as:
> def air_gamma_0(t, far=0.0):
>     """
>     Specific heat ratio (gamma) of Air/JP8
>     t - static temperature, Rankine
>     [far] - fuel air ratio [- defaults to 0.0 (dry air)]
>     air_gamma - specific heat ratio
>     """
>     if far< 0.:
>         return NAN
>     elif far < 0.005:
>         ag= air_gamma_1(t)
>         ag[np.logical_or(t< 379., t> 4731.)]= NAN
>         return ag
>     elif far< 0.069:
>         ag= air_gamma_2(t, far)
>         ag[np.logical_or(t< 699., t> 4731.)]= NAN
>         return ag
>     else:
>         return NAN
> Rest of the code is in the attachment.
>
>
> My two cents,
> eat
>
>
>
> NAN = float('nan')
>
> def air_gamma(t, far=0.0):
>     """
>     Specific heat ratio (gamma) of Air/JP8
>     t - static temperature, Rankine
>     [far] - fuel air ratio [- defaults to 0.0 (dry air)]
>     air_gamma - specific heat ratio
>     """
>     if far < 0.:
>         return NAN
>     elif far < 0.005:
>         if t < 379. or t > 4731.:
>             return NAN
>         else:
>             air_gamma = -3.472487e-22 * t ** 6. + 6.218811e-18 * t ** 5.
-
> 4.428098e-14 * t ** 4. + 1.569889e-10 * t ** 3. - 0.0000002753524 * t **
2.
> + 0.0001684666 * t + 1.368652
>     elif far < 0.069:
>         if t < 699. or t > 4731.:
>             return NAN
>         else:
>             a6 = 4.114808e-20 * far ** 3. - 1.644588e-20 * far ** 2. +
> 3.103507e-21 * far - 3.391308e-22
>             a5 = -6.819015e-16 * far ** 3. + 2.773945e-16 * far ** 2. -
> 5.469399e-17 * far + 6.058125e-18
>             a4 = 4.684637e-12 * far ** 3. - 1.887227e-12 * far ** 2. +
> 3.865306e-13 * far - 4.302534e-14
>             a3 = -0.00000001700602 * far ** 3. + 0.000000006593809 * far
**
> 2. - 0.000000001392629 * far + 1.520583e-10
>             a2 = 0.00003431136 * far ** 3. - 0.00001248285 * far ** 2. +
> 0.000002688007 * far - 0.0000002651616
>             a1 = -0.03792449 * far ** 3. + 0.01261025 * far ** 2. -
> 0.002676877 * far + 0.0001580424
>             a0 = 13.65379 * far ** 3. - 3.311225 * far ** 2. + 0.3573201
*
> far + 1.372714
>             air_gamma = a6 * t ** 6. + a5 * t ** 5. + a4 * t ** 4. + a3
* t
> ** 3. + a2 * t ** 2. + a1 * t + a0
>     elif far >= 0.069:
>         return NAN
>     else:
>         return NAN
>     return air_gamma
>
> David Parker
> Chromalloy - TDAG
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
> [attachment "air_gamma.py" deleted by Dave Parker/Chromalloy]
> _______________________________________________
>
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
>
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
>
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at scipy.org
> http://mail.scipy.org/mailman/listinfo/numpy-discussion
>
>
_______________________________________________
NumPy-Discussion mailing list
NumPy-Discussion at scipy.org
http://mail.scipy.org/mailman/listinfo/numpy-discussion

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/numpy-discussion/attachments/20110201/df389f0d/attachment.html>
```