aeengineer
aeengineer

Reputation: 85

How to plot function results with matplotlib in python

I have made a function which returns a value for a force depending on the z position (z_pos). I would like to plot these results (shear diagram for the engineers here), however I get the following error:

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

I have tried it both with arange and linspace, see the code here:

import matplotlib.pyplot as plt
import numpy as np

#values in kN and m
FyFL = 520
FyRL = 1246
L = 40.
Lf1 = 2.
Lf2 = 25.5
g = 9.81
W = 60000
q = (3*g*W/L)/1000 #kN/m
print q 

def int_force_y(FyFL, FyRL, L, Lf1, Lf2, q, z_pos):

    if z_pos <= Lf1:
        int_fc_y = -q*z_pos
    elif z_pos > Lf1 and z_pos < Lf1+Lf2:
        int_fc_y = -q*Lf1 + FyFL-q*z_pos
    elif z_pos >= Lf2 and z_pos <= 40.:
        int_fc_y = -q*Lf1 + FyFL-q*(Lf1+Lf2)-q*z_pos
    else:
        return "No valid z_pos"

    return int_fc_y

z_pos = np.arange(0,41,1)
y = int_force_y(FyFL, FyRL, L, Lf1, Lf2, q, z_pos)
plt.plot(z_pos,y)
plt.show()

Help is very much appreciated!

Upvotes: 0

Views: 286

Answers (2)

jotasi
jotasi

Reputation: 5177

The error you are getting has nothing to do with the plotting but arises when you call int_force_y. The argument z_pos is a np.ndarray. If you now compare this to eg. Lf1 in your function then this gives you a boolean array where each element indicates if the corresponding element of z_pos is smaller or equal to Lf1 in case of your first if statement. As some elements are smaller or equal and some are not, he cannot decide whether he should consider this as True or False and asks you to use .any() to indicate that it should be True if any element is True or .all() to indicate that it should be True if all elements are True.

But both or these cases do not do what you want them to do. You want a decision for each element individually and to then set the corresponding value in int_fc_y accordingly. You can do this by a for-loop or more elegantly by using boolean indexing and np.logical_and. Just use this function to produce your result array instead of your version:

def int_force_y(FyFL, FyRL, L, Lf1, Lf2, q, z_pos):
    if (z_pos>40.).any():
        return "No valid z_pos"
    int_force_y = np.zeros_like(z_pos)
    int_fc_y[z_pos<=Lf1] = -q*z_pos
    int_fc_y[np.logical_and(z_pos > Lf1,
                            z_pos < Lf1+Lf2)] = -q*Lf1 + FyFL-q*z_pos
    int_fc_y[np.logical_and(z_pos >= Lf2,
                            z_pos <= 40.)] = -q*Lf1 + FyFL-q*(Lf1+Lf2)-q*z_pos
    return int_fc_y

Upvotes: 1

Numlet
Numlet

Reputation: 837

The problem happens because you are asking python whether if an array is larger or smaller than certain value:

if z_pos <= Lf1:

This might be truth for some values and false for some others, with leaves the question of whether if that statement is true or false ambiguous.

You can try :

if np.array(z_pos <= Lf1).any():

or

if np.array(z_pos <= Lf1).all():

depending on what you want. Same for the following if statements.

Upvotes: 0

Related Questions