# How to calculate a function with different equations depending on different ranges?

## Question:

I am trying to calculate this equation in python.

However I seem to be unable to perform the logic operation as had to use array in np to create the decimal range.

I wonder if there is an alternative method of creating the range without np, or an alternative method of perform logic on this.

I would appreciate help on this problem as I am still learning, thank you!

This is what I’ve tried below.

Although I am getting a syntax error:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Did try np.logical_and without success.

```
# Cardiac Elastance and Compliance Calculation
import numpy as np
# Timestep for one cardiac cycle
# Creates from 0 to 1 spaced by 0.02
x = np.linspace(0, 1, num=51)
# Time of ventricular contraction and relaxation
T_vc = 0.25
T_vr = 0.125
#Ventricles
def vent_elastance(x):
if x >= 0 and x <= T_vc:
return 0.5 - 0.5 * cos(pi*x/T_vc)
#elif x > T_vc and x <= (T_vc + T_vr):
#return 0.5 + 0.5 * cos (pi * (x-T_vc) / T_vr )
#else:
#return 0
y = vent_elastance(x)
```

## Answers:

The syntax error is with the ‘if’ statement.

try `if x >= 0 and x <= T_vc:`

and then the code. No, I don’t think this is possible outside NumPy, but this is a bit outside my skill set. Judging from the equation, I’d say just use NumPy.

The equation you’ve shown says that `e_v`

is calculated using a different expression for different values of `x`

(or `t`

in the screenshot). To do this, you can initialize the result array to an array of zeros (or nans, if you want), and then fill the values corresponding to each group of `x`

using the expression for that group. Numpy’s vectorized math capabilities make this approach *significantly* faster than the other answers that iterate over the array and calculate each element individually.

```
def vent_elastance(x):
result = np.zeros_like(x)
# Create a boolean mask for elements of x that fulfill the first condition
condition1 = (x >= 0) & (x <= T_vc)
# Calculate the first expression for values of x that satisfy that condition,
# Then set only those values of the result
result[condition1] = 0.5 * (1 - np.cos(np.pi * x[condition1] / T_vc))
# Do the same for the second condition
condition2 = (x > T_vc) & (x <= T_vr + T_vc)
result[condition2] = 0.5 * (1 + np.cos(np.pi * (x[condition2] - T_vc) / T_vr))
# Don't need condition3 because it's zero anyway
return result
```

Comparing the runtimes of the different approaches, we see that the vectorized numpy approach clearly beats Ori’s list comprehension and user19077881’s for loop when the input `x`

is larger than ~100 elements. Here, I defined `x`

as `np.linspace(0, 1, N)`

, where `N`

is the input size shown on the x-axis.

You need to be clear if you are dealing with a List of values or values in sequence. This answer deals with the values one at a time; other answer operate on the whole array at once :

```
# Cardiac Elastance and Compliance Calculation
import numpy as np
import math as m
# Timestep for one cardiac cycle
# Creates from 0 to 1 spaced by 0.02
x = np.linspace(0, 1, num=51)
# Time of ventricular contraction and relaxation
T_vc = 0.25
T_vr = 0.125
#Ventricles
def vent_elastance(xlist):
result = []
for t in xlist:
if t >= 0 and t <= T_vc:
result.append(0.5 - 0.5 * m.cos(m.pi*t/T_vc))
elif t > T_vc and t <= (T_vc + T_vr):
result.append(0.5 + 0.5 * m.cos (m.pi * (t-T_vc) / T_vr ))
else:
result.append(0)
return result
y = vent_elastance(x)
print(y)
```

Use the function with list comprehension:

```
import numpy as np
# Timestep for one cardiac cycle
# Creates from 0 to 1 spaced by 0.02
x = np.linspace(0, 1, num=51)
# Time of ventricular contraction and relaxation
T_vc = 0.25
T_vr = 0.125
#Ventricles
def vent_elastance(x):
if x >= 0 and x <= T_vc:
return 0.5 - 0.5 * np.cos(np.pi*x/T_vc)
elif x > T_vc and x <= (T_vc + T_vr):
return 0.5 + 0.5 * np.cos(np.pi * (x-T_vc) / T_vr )
else:
return 0
y = [vent_elastance(_x) for _x in x]
print(y)
```

Outputs:

```
[0.0, 0.015708419435684462, 0.06184665997806821, 0.13551568628929422, 0.23208660251050173, 0.3454915028125263, 0.46860474023534326, 0.5936906572928624, 0.7128896457825363, 0.8187119948743449, 0.9045084971874737, 0.9648882429441257, 0.9960573506572389, 0.9842915805643155, 0.8644843137107056, 0.6545084971874738, 0.4063093427071376, 0.18128800512565496, 0.03511175705587444, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
```

Also, you could just `vectorize`

the function:

```
vent_elastance = np.vectorize(vent_elastance)
y = vent_elastance(x)
```

I’ve also just managed to do it like this, so happy to have learnt all the ways

```
import math
#Timestep for one cardiac cycle
#Creates from 0 to 1 spaced by 0.02
x = [i/100 for i in range(0, 102, 2)]
#Time of ventricular contraction and relaxation
T_vc = 0.25
T_vr = 0.125
#Ventricles
def vent_elastance(x):
if x >= 0 and x <= T_vc:
return 0.5 - 0.5 * math.cos(math.pi*x/T_vc)
elif x > T_vc and x <= (T_vc + T_vr):
return 0.5 + 0.5 * math.cos (math.pi * (x-T_vc) / T_vr )
else:
return 0
print([vent_elastance(i) for i in x])
```

My understanding is that you would like to use vent_elastance on each element of x and y will be the vector built out of these elements. On the syntax errors:

instead of `if x >= 0 and x <= T_vc`

you need `if x >= 0 and x <= T_vc:`

trailing `:`

is always required for if statements. `cos`

and `pi`

are not in python by default, they have to be imported.

My code:

```
# Cardiac Elastance and Compliance Calculation
import numpy as np
from math import cos, pi
# Timestep for one cardiac cycle
# Creates from 0 to 1 spaced by 0.02
x = np.linspace(0, 1, num=51)
# Time of ventricular contraction and relaxation
T_vc = 0.25
T_vr = 0.125
#Ventricles
def vent_elastance(x):
if x >= 0 and x <= T_vc:
return 0.5 - 0.5 * cos(pi*x/T_vc)
elif x > T_vc and x <= (T_vc + T_vr):
return 0.5 + 0.5 * cos (pi * (x-T_vc) / T_vr )
else:
return 0
y = np.vectorize(vent_elastance)(x)
print(y)
```

output:

```
[0. 0.01570842 0.06184666 0.13551569 0.2320866 0.3454915
0.46860474 0.59369066 0.71288965 0.81871199 0.9045085 0.96488824
0.99605735 0.98429158 0.86448431 0.6545085 0.40630934 0.18128801
0.03511176 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0.
0. 0. 0. ]
```