Reputation: 79
I'm trying to design a function that takes two lists (t
,v
), one representing the time of a moving object, and the second representing the speed of the object at the corresponding time, and uses them to draw a location/time graph.
e.g. t=[1,2,3]
, v=[3,4,6]
. At t[0]
the object speed is [0]
and so forth.
Between each point of time the object's acceleration changes and the function must calculate the different accelerations the object has according to the lists.
Currently I'm sitting on this:
def total_x_graph(t,v):
def f1(i):## acceleration
if i!=0:
return (v[i]+v[i-1])/(t[i]-t[i-1])
else:
return (v[i]/t[i])
def f2(i,j,x):## the Distance
return f1(i)/2.0*j**2+x
dx=0.1
x=0
fig,ax=plt.subplots()##the graph
for i in range(len(t)):
if i==0:
t_points=[0+dx*k for k in range(int(t[i]))]
else:
t_points=[t[i-1]+dx*k for k in range(int(t[i]-t[i-1]))]
y=[f2(i,j,x) for j in range(len(t_points))]
ax.plot(t_points,y,color='red',label='1',linewidth=2)
x+=f2(i,t_points[-1],x)
ax.set_xlabel('time')
ax.set_ylabel('Distance')
ax.legend()
ax.grid(True)
plt.show()
When I run the function it doesn't create a graph, for example when I enter in the shell total_x_graph([1,2,3],[3,4,6])
this is what is shown:
Is the problem in the programming? If it is thank you in advance for any help ^^.
Upvotes: 0
Views: 653
Reputation: 35175
The programming answer is that since your t
array has a difference of 1 between its elements, your plotting commands always get a single data point to plot (in the loop over i
, in both branches of the if
you essentially have range(1)
in the list comprehension, which is simply [0]
). This means that there is no line to draw, since t_points
and y
are both one-element lists. If you set a marker for the plots, you'll see the single data points, one for each iteration of i
(corresponding to the legend).
The larger issue is physical. First, the acceleration contains
(v[i]-v[i-1])/(t[i]-t[i-1])
rather than the sum of the two velocities in the numerator. But I don't really see why you want to use the acceleration: you will get a more direct answer by integrating v
vs. t
, i.e. in each time step, starting from t=0
and x=0
, adding x+=v[i]*(t[i]-t[i-1])
, or something similar.
It is also unclear what exactly you're trying to plot: why a loop over every time step? I think you would want to do a loop once to get an array y
(or x
, doesn't matter) displacement to each of your t
values, then plot them together in a single call to ax.plot()
.
This is what I would do, using numpy
to make my life easier:
import numpy as np
import matplotlib.pyplot as plt
def total_x_graph(t,v):
x0 = 0
x = x0 + np.cumsum(v*np.diff(np.append(0,t)))
fig,ax=plt.subplots()
ax.plot(t,x,'ro-',linewidth=2)
ax.set_xlabel('time')
ax.set_ylabel('distance')
ax.legend()
ax.grid(True)
plt.show()
Calling then total_x_graph([1,2,3],[4,5,6])
gives me
The only non-trivial part of the code is
x = x0 + np.cumsum(v*np.diff(np.append(0,t)))
This computes the displacement by successively adding up v*dt
kind of values. Inside, np.append(0,t)
will add a 0
as a first time value, so that a call to np.diff()
(computing t[i]-t[i-1]
for you) will return an array of the same length as t
originally. Then we multiply this array with v
(elementwise), which makes this result automatically an array (rather than a list). A final call to np.cumsum()
computes the cumulative sum, which is the simplest option of integrating the velocity to obtain displacement. You could even use a custom starting position x0
, I set this to be 0
.
Upvotes: 1
Reputation: 11
I think the problem is the way that you a generating your data to plot. At the moment you are trying to plot a line with only one point which is impossible.
Take a look at the data you are plotting using the print command. i.e.
print t_points
print y
Also changing your graph to plot point markers may help you see what you are plotting now better. i.e. change your plot command to something like:
ax.plot(t_points,y,'ro',color='red',label='1',linewidth=2, markersize=10)
This will let you see what you are actually plotting.
Upvotes: 0