Re: [Numpy-discussion] Vectorize or rewrite function to work with array inputs?
Thanks for the advice. 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.ta...@gmail.com To: Discussion of Numerical Python numpy-discussion@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-boun...@scipy.org Hi, On Mon, Jan 31, 2011 at 5:15 PM, dpar...@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.002753524 * 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.0001700602 * far ** 3. + 0.6593809 * far ** 2. - 0.1392629 * far + 1.520583e-10 a2 = 0.3431136 * far ** 3. - 0.1248285 * far ** 2. + 0.02688007 * far - 0.002651616 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@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@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion ___ NumPy-Discussion mailing list NumPy-Discussion@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion
Re: [Numpy-discussion] Vectorize or rewrite function to work with array inputs?
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[far0.005] = -3.472487e-22 * t ** 6. + 6.218811e-18 * t ** 5. - 4.428098e-14 * t ** 4. + \ 1.569889e-10 * t ** 3. - 0.002753524 * 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[(far0.) | (far0.069)] = np.nan t[(t 379.) | (t 4731.)] = np.nan ag[(far0.005)] = -3.472487e-22 * t ** 6. + 6.218811e-18 * t ** 5. - 4.428098e-14 * t ** 4. + 1.569889e-10 * t ** 3. - 0.002753524 * 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.0001700602 * far ** 3. + 0.6593809 * far ** 2. - 0.1392629 * far + 1.520583e-10 a2 = 0.3431136 * far ** 3. - 0.1248285 * far ** 2. + 0.02688007 * far - 0.002651616 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 jsalv...@u.washington.edu To: Discussion of Numerical Python numpy-discussion@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-boun...@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, dpar...@chromalloy.com wrote: Thanks for the advice. 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.ta...@gmail.com To:Discussion of Numerical Python numpy-discussion@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-boun...@scipy.org Hi, On Mon, Jan 31, 2011 at 5:15 PM, dpar...@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
Re: [Numpy-discussion] Vectorize or rewrite function to work with array inputs?
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 broadcastable. Still the code seems like an ugly hack... David Parker Chromalloy - TDAG From: josef.p...@gmail.com To: Discussion of Numerical Python numpy-discussion@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-boun...@scipy.org On Tue, Feb 1, 2011 at 3:20 PM, dpar...@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[far0.005] = -3.472487e-22 * t ** 6. + 6.218811e-18 * t ** 5. - 4.428098e-14 * t ** 4. + \ 1.569889e-10 * t ** 3. - 0.002753524 * 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[y10] = y Traceback (most recent call last): File pyshell#8, line 1, in module x[y10] = 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[(far0.) | (far0.069)] = np.nan t[(t 379.) | (t 4731.)] = np.nan ag[(far0.005)] = -3.472487e-22 * t ** 6. + 6.218811e-18 * t ** 5. - 4.428098e-14 * t ** 4. + 1.569889e-10 * t ** 3. - 0.002753524 * 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.0001700602 * far ** 3. + 0.6593809 * far ** 2. - 0.1392629 * far + 1.520583e-10 a2 = 0.3431136 * far ** 3. - 0.1248285 * far ** 2. + 0.02688007 * far - 0.002651616 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 the broadcasting would avoid the calculations on the broadcasted array and only broad cast before the assignment maybe something like this with t that is not broadcasted cond = (far0.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.002753524 * t ** 2. + 0.0001684666 * t + 1.368652))[cond] Josef David Parker Chromalloy - TDAG From:John Salvatier jsalv...@u.washington.edu To:Discussion of Numerical Python numpy-discussion@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-boun...@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
[Numpy-discussion] Vectorize or rewrite function to work with array inputs?
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. 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.002753524 * 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.0001700602 * far ** 3. + 0.6593809 * far ** 2. - 0.1392629 * far + 1.520583e-10 a2 = 0.3431136 * far ** 3. - 0.1248285 * far ** 2. + 0.02688007 * far - 0.002651616 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@scipy.org http://mail.scipy.org/mailman/listinfo/numpy-discussion