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

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

```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
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

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.

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

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