I'm trying to plot the fall of an object (an optical fork to be precise) as a function of time in order to verify that the law of gravity is indeed 9.81. The different data are supposed to represent the passage at each slot. The different slits are spaced 1 centimeter apart and there are 11 slits in all. I measured these data with an Arduino setup and I plot the graph and fit with Python. However, depending on whether I enter the values manually or by reading the CSV file containing these same values, I get two completely different outputs. Here is the code I use when I enter the values manually:
import numpy as np # For the calculation
import pandas as pd # To read files
import matplotlib.pyplot as plt # To draw curves
import scipy.optimize as opt # For the adjustment
# Raw data
#t = 1e-3 * np.array([7.038,10.574,14.122,17.684,21.258,24.84,28.434,32.032,35.642,39.26,42.886])
z = -0.01 * np.linspace(1, 11, 11)
# Definition of the free fall function
g = 9.81 # the acceleration of gravity
def f(t,t0,h0): # Definition of the fitting function
return -0.5*g*(t-t0)**2 + h0
# Data adjustment
init_param = [0 , 0] # Initial values t0=0, h0=0
final_param , var = opt.curve_fit(f,t,z)
# Optimal function
tt = np.linspace(final_param[0], 100e-3,100)
hh = f(tt, *final_param) # Reconstruction of the fitted curve
# Plot of analyzed data
plt.clf() # Plot of data and fit
plt.xlabel("Time (s)")
plt.ylabel("Height (m)")
legend = "t0 = %f ms, h0 = %f centimeter " % (final_param[0]*1000,final_param[1]*100)
plt.plot(tt,hh,"r--",label=legend) # The adjustment
plt.plot(t,z,"bo", label="Data") # The data
plt.legend()
This is the output I get with this code:
And here is the code I use when I read the values directly from the CSV file without entering it manually:
import numpy as np # For the calculation
import pandas as pd # To read files
import matplotlib.pyplot as plt # To draw curves
import scipy.optimize as opt # For the adjustment
# Raw data
data = pd.read_csv("Test.csv", sep=";") # Opening the data file
timeData = data['Sum of the times (s)']
disData = data['Distance (m)']
t = np.array(timeData[3:13]) # extracts data between 3.524 and 3.626 s
z = np.array(disData[3:13])
t = 1e-3 * t
z = -0.01 * z
# Definition of the free fall function
g = 9.81 # the acceleration of gravity
def f(t,t0,h0): # Definition of the fitting function
return -0.5*g*(t-t0)**2 + h0
# Data adjustment
init_param = [0 , 0] # Initial values t0=0, h0=0
final_param , var = opt.curve_fit(f,t,z,init_param)
# Optimal function
tt = np.linspace(final_param[0], 100e-3,100)
hh = f(tt, *final_param) # Reconstruction of the fitted curve
# Plot of analyzed data
plt.clf() # Plot of data and fit
plt.xlabel("Time (s)")
plt.ylabel("Height (m)")
legend = "t0 = %f ms, h0 = %f centimeter " % (final_param[0]*1000,final_param[1]*100)
plt.plot(tt,hh,"r--",label=legend) # The adjustment
plt.plot(t,z,"bo", label="Data") # The data
plt.legend()
And this is the result I get with this second code:
Last, here is the CSV file that I use in my second code with name 'Test.csv':
T (s) | Distance (m) | Sum of the times (s) |
---|---|---|
3.514 | 0.000 | 3.514 |
3.524 | 0.010 | 7.038 |
3.536 | 0.020 | 10.574 |
3.548 | 0.030 | 14.122 |
3.562 | 0.040 | 17.684 |
3.574 | 0.050 | 21.258 |
3.582 | 0.060 | 24.84 |
3.592 | 0.070 | 28.434 |
3.6 | 0.080 | 32.032 |
3.61 | 0.090 | 35.642 |
3.618 | 0.100 | 39.26 |
3.626 | 0.110 | 42.886 |
3.636 | 0.120 | 46.522 |
I specify that I don't take the first and the last value of the table because the edges of the fork measure more than one centimeter.
My two codes work but as you can see, I get two totally different outputs even though the values are the same. What do you think could be the cause?
I was unable to run your second snippet because it gave an error that x_util
is not defined, but the issue is mostly with z
. In the first code, you multiply it by -0.01
in order to get the range:
[-0.01 -0.02 -0.03 -0.04 -0.05 -0.06 -0.07 -0.08 -0.09 -0.1 -0.11]
However, the CSV already has them at the correct scale, so by continuing to do that multiplication, you instead get:
[-0.0001 -0.0002 -0.0003 -0.0004 -0.0005 -0.0006 -0.0007 -0.0008 -0.0009
-0.001 -0.0011 -0.0012]
Just do z = -1 * z
instead.
Also, slicing [3:13]
skips the first 3 rows and starts with T=3.548 instead of T=3.524 . So to match the data of the first snippet, you'd need to slice [1:13]
.