Svavar KonrÑðsson - Fab Futures - Data Science
Home About

PresentationΒΆ

First damper datasetΒΆ

Import damper dyno data:

InΒ [1]:
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('datasets/dyno/Dempari-Ullman.csv', sep=';', decimal=",")
column_names = list(df)

Plot all variables, using the Pyplot tutorial:

InΒ [2]:
plt.figure()
for i in column_names:
    plt.plot(df[column_names[0]],df[i])
    plt.title("Ullman damper")
    plt.xlabel(column_names[0])
    plt.ylabel(i)
    plt.show()
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image

See the force as a function of the damper's position:

InΒ [3]:
time = df[column_names[0]]
position = df[column_names[7]]
force = df[column_names[8]]
plt.plot(position,force)
plt.title("Ullman damper")
plt.xlabel(column_names[7])
plt.ylabel(column_names[8])
plt.show()
No description has been provided for this image

Now we can calculate the velocity by integrating the position:

InΒ [4]:
velocity = []
for i in range(1, len(time)-1):
    v = (position[i+1]-position[i-1])/(time[i+1]-time[i-1])
    velocity = velocity + [v]
# print(len(time))
# print(velocity)
plt.plot(velocity,force[1:len(force)-1])
plt.title("Ullman damper")
plt.xlabel("Velocity [mm/s]")
plt.ylabel(column_names[8])
Out[4]:
Text(0, 0.5, 'Load(8503:Load) (kN)')
No description has been provided for this image

Now I see that this is the wrong dataset. This is a test done on a very low speed Instron universal testing machine, not on a damper dynamometer. So it doesn't give useful info.

Second damper datasetΒΆ

Let's try importing better data (with help from Stack Overflow and I saved the data to a v7 version of a mat file from MATLAB, as suggested here):

InΒ [5]:
# Source - https://stackoverflow.com/a
# Posted by Gilad Naor, modified by community. See post 'Timeline' for change history
# Retrieved 2025-12-11, License - CC BY-SA 4.0

import scipy.io as scio
ullman = scio.loadmat('datasets/dyno/python_ullman.mat')
ullman.keys()
# print(ullman['a'])
# print(ullman.values())
# print(ullman.items())
Out[5]:
dict_keys(['__header__', '__version__', '__globals__', 'a'])

I can load the .mat file. Let's look at the header:

InΒ [6]:
ullman['__header__']
Out[6]:
b'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Thu Dec 11 09:23:40 2025'
InΒ [7]:
ullman['__version__']
Out[7]:
'1.0'
InΒ [8]:
ullman['__globals__']
Out[8]:
[]

The variable that I saved as a MATLAB .mat file was called a. Let's have a look at it:

InΒ [9]:
ullman['a']
Out[9]:
array([[(array([[(array(['C:\\Users\\svava\\Documents\\CTW Automation\\Data\\SAFESeat1-Ullman.dctw'],
                      dtype='<U66'), array([[(array([[(array(['Notes'], dtype='<U5'), array([], dtype='<U1'), array(['Notes : Ullman dynamics damper from Ullman Biscaya seat. Unknown adjustment. There seems to be an adjustment screw.'],
                                      dtype='<U115'))                                                                                                                                                                 ]],
                              dtype=[('Name', 'O'), ('Description', 'O'), ('Value', 'O')]), array([[(array(['Amplitude'], dtype='<U9'), array(['mm'], dtype='<U2'), array([[25.02304691]]))],
                               [(array(['RodForce'], dtype='<U8'), array(['N'], dtype='<U1'), array([[166.04866452]]))],
                               [(array(['SampleFrequency'], dtype='<U15'), array(['Hz'], dtype='<U2'), array([[1000]], dtype=uint16))],
                               [(array(['Speed'], dtype='<U5'), array(['m/s'], dtype='<U3'), array([[0.6]]))],
                               [(array(['Stroke'], dtype='<U6'), array(['mm'], dtype='<U2'), array([[50.04609382]]))],
                               [(array(['RodDiameter'], dtype='<U11'), array(['mm'], dtype='<U2'), array([[16.]]))],
                               [(array(['RodForceReboundReading'], dtype='<U22'), array(['N'], dtype='<U1'), array([[157.22724199]]))],
                               [(array(['Frequency'], dtype='<U9'), array(['Hz'], dtype='<U2'), array([[3.81620057]]))],
                               [(array(['RodForceCompressionReading'], dtype='<U26'), array(['N'], dtype='<U1'), array([[174.87008706]]))],
                               [(array(['GasPressure'], dtype='<U11'), array(['bar'], dtype='<U3'), array([[8.25858306]]))]],
                              dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')]), array([[(array(['Displacement'], dtype='<U12'), array(['mm'], dtype='<U2'), array([[-7.86976738, -7.86999614, -7.87182926, ..., 24.33937498,
                                        24.21426138, 24.07536487]], shape=(1, 45548)))                                                                              ],
                               [(array(['Force'], dtype='<U5'), array(['N'], dtype='<U1'), array([[-136.48410812, -136.4807845 , -136.45690685, ...,   91.31654695,
                                          77.52026951,   64.22820974]], shape=(1, 45548)))                                                                         ],
                               [(array(['Temperature'], dtype='<U11'), array(['C'], dtype='<U1'), array([[30.02929688, 30.02929688, 29.9987793 , ..., 30.79223633,
                                        30.85327148, 30.79223633]], shape=(1, 45548)))                                                                            ],
                               [(array(['Velocity'], dtype='<U8'), array(['m/s'], dtype='<U3'), array([[3.13236326e-05, 6.23623033e-04, 3.65981696e-03, ...,
                                        7.96180025e-02, 8.00163916e-02, 1.41805509e-01]], shape=(1, 45548)))                                                ],
                               [(array(['Time'], dtype='<U4'), array(['s'], dtype='<U1'), array([[0.0000e+00, 1.0000e-03, 2.0000e-03, ..., 4.5545e+01, 4.5546e+01,
                                        4.5547e+01]], shape=(1, 45548)))                                                                                          ]],
                              dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')]))                                                                                                                                             ]],
                      dtype=[('fields', 'O'), ('constants', 'O'), ('signals', 'O')]))                                                                                                                                                       ]],
              dtype=[('File', 'O'), ('Data', 'O')]),)                                                                                                                                                                                          ]],
      dtype=[('files', 'O')])

This data structure is really annoying. I need to dig deep into it to find the actual data.

InΒ [10]:
ullman['a'][0][0][0][0][0][0][0][0]
Out[10]:
'C'

OK, now I'm finally getting somewhere:

InΒ [11]:
ullman['a'][0][0][0][0][0][1][0][0][1]
Out[11]:
array([[(array(['Amplitude'], dtype='<U9'), array(['mm'], dtype='<U2'), array([[25.02304691]]))],
       [(array(['RodForce'], dtype='<U8'), array(['N'], dtype='<U1'), array([[166.04866452]]))],
       [(array(['SampleFrequency'], dtype='<U15'), array(['Hz'], dtype='<U2'), array([[1000]], dtype=uint16))],
       [(array(['Speed'], dtype='<U5'), array(['m/s'], dtype='<U3'), array([[0.6]]))],
       [(array(['Stroke'], dtype='<U6'), array(['mm'], dtype='<U2'), array([[50.04609382]]))],
       [(array(['RodDiameter'], dtype='<U11'), array(['mm'], dtype='<U2'), array([[16.]]))],
       [(array(['RodForceReboundReading'], dtype='<U22'), array(['N'], dtype='<U1'), array([[157.22724199]]))],
       [(array(['Frequency'], dtype='<U9'), array(['Hz'], dtype='<U2'), array([[3.81620057]]))],
       [(array(['RodForceCompressionReading'], dtype='<U26'), array(['N'], dtype='<U1'), array([[174.87008706]]))],
       [(array(['GasPressure'], dtype='<U11'), array(['bar'], dtype='<U3'), array([[8.25858306]]))]],
      dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')])

Let's try to get at the Amplitude data:

InΒ [12]:
ullman['a'][0][0][0][0][0][1][0][0][1][0]
Out[12]:
array([(array(['Amplitude'], dtype='<U9'), array(['mm'], dtype='<U2'), array([[25.02304691]]))],
      dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')])
InΒ [13]:
ullman['a'][0][0][0][0][0][1][0][0][1][0][0]
Out[13]:
np.void((array(['Amplitude'], dtype='<U9'), array(['mm'], dtype='<U2'), array([[25.02304691]])), dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')])

Here's the title 'Amplitude':

InΒ [14]:
ullman['a'][0][0][0][0][0][1][0][0][1][0][0][0]
Out[14]:
array(['Amplitude'], dtype='<U9')

And here's the actual number:

InΒ [15]:
ullman['a'][0][0][0][0][0][1][0][0][1][0][0][2]
Out[15]:
array([[25.02304691]])

Finally, a number! Let's try to get at the timeseries:

InΒ [16]:
ullman['a'][0][0][0][0][0][1][0][0][2]
Out[16]:
array([[(array(['Displacement'], dtype='<U12'), array(['mm'], dtype='<U2'), array([[-7.86976738, -7.86999614, -7.87182926, ..., 24.33937498,
                24.21426138, 24.07536487]], shape=(1, 45548)))                                                                              ],
       [(array(['Force'], dtype='<U5'), array(['N'], dtype='<U1'), array([[-136.48410812, -136.4807845 , -136.45690685, ...,   91.31654695,
                  77.52026951,   64.22820974]], shape=(1, 45548)))                                                                         ],
       [(array(['Temperature'], dtype='<U11'), array(['C'], dtype='<U1'), array([[30.02929688, 30.02929688, 29.9987793 , ..., 30.79223633,
                30.85327148, 30.79223633]], shape=(1, 45548)))                                                                            ],
       [(array(['Velocity'], dtype='<U8'), array(['m/s'], dtype='<U3'), array([[3.13236326e-05, 6.23623033e-04, 3.65981696e-03, ...,
                7.96180025e-02, 8.00163916e-02, 1.41805509e-01]], shape=(1, 45548)))                                                ],
       [(array(['Time'], dtype='<U4'), array(['s'], dtype='<U1'), array([[0.0000e+00, 1.0000e-03, 2.0000e-03, ..., 4.5545e+01, 4.5546e+01,
                4.5547e+01]], shape=(1, 45548)))                                                                                          ]],
      dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')])
InΒ [17]:
ullman_displacement_name = ullman['a'][0][0][0][0][0][1][0][0][2][0][0][0][0]
InΒ [18]:
ullman_displacement_unit = ullman['a'][0][0][0][0][0][1][0][0][2][0][0][1][0]
InΒ [19]:
ullman_displacement = ullman['a'][0][0][0][0][0][1][0][0][2][0][0][2][0][11500:]
InΒ [20]:
ullman['a'][0][0][0][0][0][1][0][0][2][1]
Out[20]:
array([(array(['Force'], dtype='<U5'), array(['N'], dtype='<U1'), array([[-136.48410812, -136.4807845 , -136.45690685, ...,   91.31654695,
                 77.52026951,   64.22820974]], shape=(1, 45548)))                                                                         ],
      dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')])
InΒ [21]:
ullman_force_name = ullman['a'][0][0][0][0][0][1][0][0][2][1][0][0][0]
InΒ [22]:
ullman_force_unit = ullman['a'][0][0][0][0][0][1][0][0][2][1][0][1][0]
InΒ [23]:
ullman_force = ullman['a'][0][0][0][0][0][1][0][0][2][1][0][2][0][11500:]

Force vs. displacement (football plot)ΒΆ

InΒ [24]:
plt.plot(ullman_displacement,ullman_force)
plt.xlabel(ullman_displacement_name + ' [' + ullman_displacement_unit + ']')
plt.ylabel(ullman_force_name + ' [' + ullman_force_unit + ']')
plt.show()
No description has been provided for this image
InΒ [25]:
import numpy as np
k = np.polyfit(ullman_displacement, ullman_force,1)
print(k[1])
k_eval = np.poly1d(k)

plt.plot(ullman_displacement,k_eval(ullman_displacement),color='red')
plt.text(15,-460,'k = ' + str(round(k[1])) + ' N/mm',color='red')
plt.plot(ullman_displacement,ullman_force)
plt.title("Linear fit to find the stiffness due to the nitrogen charge")
plt.xlabel(ullman_displacement_name + ' [' + ullman_displacement_unit + ']')
plt.ylabel(ullman_force_name + ' [' + ullman_force_unit + ']')
plt.show()
185.5948566809324
No description has been provided for this image
InΒ [26]:
ullman['a'][0][0][0][0][0][1][0][0][2][1]
Out[26]:
array([(array(['Force'], dtype='<U5'), array(['N'], dtype='<U1'), array([[-136.48410812, -136.4807845 , -136.45690685, ...,   91.31654695,
                 77.52026951,   64.22820974]], shape=(1, 45548)))                                                                         ],
      dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')])

Now I need to find the velocity timeseries:

InΒ [27]:
ullman['a'][0][0][0][0][0][1][0][0][2][3]
Out[27]:
array([(array(['Velocity'], dtype='<U8'), array(['m/s'], dtype='<U3'), array([[3.13236326e-05, 6.23623033e-04, 3.65981696e-03, ...,
               7.96180025e-02, 8.00163916e-02, 1.41805509e-01]], shape=(1, 45548)))                                                ],
      dtype=[('Name', 'O'), ('Units', 'O'), ('Value', 'O')])
InΒ [38]:
ullman_velocity_name = ullman['a'][0][0][0][0][0][1][0][0][2][3][0][0][0]
InΒ [39]:
ullman_velocity_unit = ullman['a'][0][0][0][0][0][1][0][0][2][3][0][1][0]
InΒ [40]:
ullman_velocity = ullman['a'][0][0][0][0][0][1][0][0][2][3][0][2][0][11500:]

I also want to plot the raw data and for that I need the time:

InΒ [45]:
ullman_time_name = ullman['a'][0][0][0][0][0][1][0][0][2][4][0][0][0]
print(ullman_time_name)
Time
InΒ [46]:
ullman_time_unit = ullman['a'][0][0][0][0][0][1][0][0][2][4][0][1][0]
InΒ [47]:
ullman_time = ullman['a'][0][0][0][0][0][1][0][0][2][4][0][2][0][11500:]

Raw data plotsΒΆ

InΒ [55]:
plt.subplot(3,1,1)
plt.plot(ullman_time,ullman_displacement)
plt.ylabel(ullman_displacement_name)
plt.subplot(3,1,2)
plt.plot(ullman_time,ullman_velocity)
plt.ylabel(ullman_velocity_name)
plt.subplot(3,1,3)
plt.plot(ullman_time,ullman_force)
plt.xlabel(ullman_time_name)
plt.ylabel(ullman_force_name)
plt.show()
No description has been provided for this image

Force vs. velocityΒΆ

InΒ [31]:
plt.plot(ullman_velocity,ullman_force)
plt.xlabel(ullman_velocity_name + ' [' + ullman_velocity_unit + ']')
plt.ylabel(ullman_force_name + ' [' + ullman_force_unit + ']')
plt.show()
No description has been provided for this image

Velocity peaksΒΆ

In order to construct a PVP plot (peak velocity vs. peak force), I need to find the velocity peaks. I can use scipy.signal.find_peaks to do that:

InΒ [32]:
import scipy.signal as signal
ullman_velocity_peaks_positive = signal.find_peaks(ullman_velocity, prominence=0.2)
# print(ullman_velocity_peaks_positive)
ullman_velocity_peaks_negative = signal.find_peaks(-ullman_velocity, prominence=0.2)
# ullman_velocity_peaks_negative2 = -1*ullman_velocity_peaks_negative
# print(ullman_velocity_peaks_negative2)
ullman_velocity_peaks = [ullman_velocity_peaks_negative, ullman_velocity_peaks_positive]
# print(ullman_velocity_peaks)
#print(ullman_velocity_peaks)
plt.plot(ullman_velocity,ullman_force)
plt.scatter(ullman_velocity[ullman_velocity_peaks_negative[0]], ullman_force[ullman_velocity_peaks_negative[0]],color = 'red')
plt.scatter(ullman_velocity[ullman_velocity_peaks_positive[0]], ullman_force[ullman_velocity_peaks_positive[0]],color = 'lime')
plt.title("Velocity peaks found using scipy.signal.find_peaks")
plt.xlabel(ullman_velocity_name + ' [' + ullman_velocity_unit + ']')
plt.ylabel(ullman_force_name + ' [' + ullman_force_unit + ']')
plt.show()
No description has been provided for this image

Damping curve (PVP plot)ΒΆ

If I plot only the velocity peaks, I get the damping curve of the damper (the PVP plot):

InΒ [33]:
plt.scatter(ullman_velocity[ullman_velocity_peaks_negative[0]], ullman_force[ullman_velocity_peaks_negative[0]],color = 'red')
plt.scatdata:image/png;base64,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RUWFHnroIaWlpSkiIkJdunTRX//6V+82ZeB3119/venevbvZtGmT2bRpk+nevbsZPnz4OV/z2WefmQ4dOpj777/ffPTRR2b//v3mX//6lzly5Iifug6cxsxXjbVr15rLL7/cJCUlmWeeeca3jQYJT+frxIkTZvDgwWblypXm448/Nps3bzZ9+/Y1vXv39mPX/rFixQrTsmVL8/zzz5s9e/aYnJwc06ZNG/Pll1/WWf/555+b1q1bm5ycHLNnzx7z/PPPm5YtW5rVq1f7ufPA8XTOcnJyzBNPPGE++OADs2/fPjNz5kzTsmVL89FHH/m588DwdL5qnDhxwlx44YVmyJAh5vLLL/dPs0GgMfM1YsQI07dvX5Ofn28OHDhg3n//ffPee+95tS/CkZ/t2bPHSDL/+c9/HGObN282kszHH39c7+vGjBljbr/9dn+0GFQaO1/GGFNUVGSSk5PNrl27TFpaWrMIR+czX84++OADI6nB/6CHmp/85CdmwoQJLmOXXHKJefDBB+usnzFjhrnkkktcxu69915z1VVX+azHYOPpnNWlW7du5pFHHvF2a0GpsfM1ZswY89vf/tY8/PDDzSoceTpfb775pomJiTHHjh3zaV8cVvOzzZs3KyYmRn379nWMXXXVVYqJidGmTZvqfE1VVZVef/11XXzxxRo6dKg6deqkvn376pVXXvFT14HTmPmSqucsKytL999/v3784x/7o9Wg0Nj5OltpaaksFovatWvngy4Do7KyUlu3btWQIUNcxocMGVLv3GzevLlW/dChQ/Xhhx/qzJkzPus1WDRmzs5WVVWl8vJydejQwRctBpXGztfSpUu1f/9+Pfzww75uMag0Zr5ee+019enTR3PnzlVycrIuvvhiTZ8+XadPn/Zqb4QjPyspKVGnTp1qjXfq1EklJSV1vubo0aM6efKkHn/8cV1//fVat26dbrrpJtlsNm3YsMHXLQdUY+ZLkp544gmFhYVpypQpvmwv6DR2vpx99913evDBBzV27NgmdWPMr7/+Wna7XfHx8S7j8fHx9c5NSUlJnfXff/+9vv76a5/1GiwaM2dne/rpp3Xq1CmNHj3aFy0GlcbM16effqoHH3xQf//73xUW1rzuBd+Y+fr888+1ceNG7dq1S2vXrtX8+fO1evVqTZo0yau9EY68ZNasWbJYLOd8fPjhh5Iki8VS6/XGmDrHpep/eUnSyJEj9etf/1o9e/bUgw8+qOHDh4fsyaG+nK+tW7dqwYIFWrZsWb01ocaX8+XszJkzuvXWW1VVVaVFixZ5/XMEg7PnoaG5qau+rvGmzNM5q7F8+XLNmjVLK1eurDO0N1XuzpfdbtfYsWP1yCOP6OKLL/ZXe0HHkz9fVVVVslgs+vvf/66f/OQn+vnPf6558+Zp2bJlXt171Lxiqg/dd999uvXWW89Zk56erh07dujIkSO1tn311Ve10nONuLg4hYWFqVu3bi7jl156qTZu3Nj4pgPIl/NVUFCgo0eP6oILLnCM2e12TZs2TfPnz9cXX3xxXr0Hgi/nq8aZM2c0evRoHThwQO+8806T2mskVf89slqttf5FevTo0XrnJiEhoc76sLAwxcbG+qzXYNGYOauxcuVKjR8/XqtWrdLgwYN92WbQ8HS+ysvL9eGHH2rbtm267777JFV/+RtjFBYWpnXr1unaa6/1S++B0Jg/X4mJiUpOTlZMTIxj7NJLL5UxRkVFReratatXeiMceUlcXJzi4uIarOvXr59KS0v1wQcf6Cc/+Ykk6f3331dpaamuvvrqOl8THh6uK6+8Up988onL+L59+5SWlnb+zQeAL+crKyur1n+Mhw4dqqysLN11113n33wA+HK+pB+C0aeffqp33323SX7xh4eHq3fv3srPz9dNN93kGM/Pz9fIkSPrfE2/fv30z3/+02Vs3bp16tOnj1q2bOnTfoNBY+ZMqt5j9Itf/ELLly/XsGHD/NFqUPB0vqKjo7Vz506XsUWLFumdd97R6tWr1blzZ5/3HEiN+fPVv39/rVq1SidPnlTbtm0lVX8XtmjRQikpKd5rzqene6NO119/venRo4fZvHmz2bx5s7nssstqXWr9ox/9yOTl5Tme5+XlmZYtW5olS5aYTz/91CxcuNBYrVZTUFDg7/b9rjHzdbbmcrWaMZ7P15kzZ8yIESNMSkqK2b59uykuLnY8KioqAvERfKbmsuEXXnjB7Nmzx+Tm5po2bdqYL774whhjzIMPPmiysrIc9TWX8v/61782e/bsMS+88EKzvZTf3Tl7+eWXTVhYmPnjH//o8mfpxIkTgfoIfuXpfJ2tuV2t5ul8lZeXm5SUFDNq1Cize/dus2HDBtO1a1fzy1/+0qt9EY4C4NixY2bcuHEmKirKREVFmXHjxpnjx4+71EgyS5cudRl74YUXzEUXXWRatWplLr/8cvPKK6/4r+kAaux8OWtO4cjT+Tpw4ICRVOfj3Xff9Xv/vvbHP/7RpKWlmfDwcHPFFVeYDRs2OLbdeeedZuDAgS7169evN7169TLh4eEmPT3dLF682M8dB54nczZw4MA6/yzdeeed/m88QDz9M+asuYUjYzyfr71795rBgwebyMhIk5KSYqZOnWq+/fZbr/ZkMea/ZxcCAACAq9UAAACcEY4AAACcEI4AAACcEI4AAACcEI4AAACcEI4AAACcEI4AAACcEI4AAACcEI4ABK309HTNnz8/aN/P+X0tFossFotOnDjh9fc/l5qf265dO7/+XKApIxwB8Lobbrih3juxb968WRaLRR999JGfu5K2bNmie+65x/HcYrHolVde8cp7P/rooyouLna5W/j5yMzM1J/+9KcG64qLi30S+IDmjHAEwOvGjx+vd955R19++WWtbX/961/Vs2dPXXHFFX7vq2PHjmrdurVP3jsqKkoJCQmyWCzn/V7ffPONNm3apBtuuKHB2oSEBK8FMgDVCEcAvG748OHq1KmTli1b5jL+7bffauXKlRo/frwkadOmTRowYIAiIyOVmpqqKVOm6NSpU/W+78GDBzVy5Ei1bdtW0dHRGj16tI4cOeJS89prr6lPnz5q1aqV4uLiZLPZHNucD6ulp6dLkm666SZZLBalp6friy++UIsWLfThhx+6vOfChQuVlpYmT25FuWzZMrVr107/+te/9KMf/UitW7fWqFGjdOrUKb344otKT09X+/btNXnyZNntdpfXvv7667r88suVnJys48ePa9y4cerYsaMiIyPVtWtXLV261O0+AHiOcATA68LCwnTHHXdo2bJlLoFi1apVqqys1Lhx47Rz504NHTpUNptNO3bs0MqVK7Vx40bdd999db6nMUY33nijvvnmG23YsEH5+fnav3+/xowZ46h5/fXXZbPZNGzYMG3btk1vv/22+vTpU+f7bdmyRZK0dOlSFRcXa8uWLUpPT9fgwYNrhY+lS5cqOzvb471C3377rZ599lmtWLFC//d//6f169fLZrPpjTfe0BtvvKGXXnpJS5Ys0erVq11e99prr2nkyJGSpN/97nfas2eP3nzzTe3du1eLFy9WXFycR30A8JABAB/Yu3evkWTeeecdx9iAAQPMbbfdZowxJisry9xzzz0urykoKDAtWrQwp0+fNsYYk5aWZp555hljjDHr1q0zVqvVHDx40FG/e/duI8l88MEHxhhj+vXrZ8aNG1dvT87vZ4wxkszatWtdalauXGnat29vvvvuO2OMMdu3bzcWi8UcOHDA7fc1xpilS5caSeazzz5zjN17772mdevWpry83DE2dOhQc++99zqef/fddyYqKsrs2LHDGGPMDTfcYO666656f3bNz4qJiTlnDQD3secIgE9ccskluvrqq/XXv/5VkrR//34VFBToF7/4hSRp69atWrZsmdq2bet4DB06VFVVVTpw4ECt99u7d69SU1OVmprqGOvWrZvatWunvXv3SpK2b9+uQYMGnVffN954o8LCwrR27VpJ1edIXXPNNY7DcJ5o3bq1unTp4ngeHx+v9PR0tW3b1mXs6NGjjufvvPOOYmNjddlll0mSfvWrX2nFihXq2bOnZsyYoU2bNjXykwFwF+EIgM+MHz9ea9asUVlZmZYuXaq0tDRHeKmqqtK9996r7du3Ox7/7//9P3366acugaKGMabOw1rO45GRkefdc3h4uLKysrR06VJVVlbq5ZdfdgQ6T7Vs2dLlucViqXOsqqrK8dz5kJok/exnP9OXX36p3NxcHT58WIMGDdL06dMb1Q8A9xCOAPjM6NGjZbVa9fLLL+vFF1/UXXfd5QgyV1xxhXbv3q2LLrqo1iM8PLzWe3Xr1k0HDx5UYWGhY2zPnj0qLS3VpZdeKknq0aOH3n77bbf7a9myZa2ToSXpl7/8pd566y0tWrRIZ86ccTmp25eMMfrnP/+pESNGuIx37NhR2dnZ+tvf/qb58+dryZIlfukHaK4IRwB8pm3bthozZox+85vf6PDhw8rOznZse+CBB7R582ZNmjRJ27dv16effqrXXntNkydPrvO9Bg8erB49emjcuHH66KOP9MEHH+iOO+7QwIEDHSddP/zww1q+fLkefvhh7d27Vzt37tTcuXPr7S89PV1vv/22SkpKdPz4ccf4pZdeqquuukoPPPCAbrvtNq/skXLH1q1bderUKQ0YMMAx9vvf/16vvvqqPvvsM+3evVv/+te/HGEQgG8QjgD41Pjx43X8+HENHjxYF1xwgWO8R48e2rBhgz799FNlZGSoV69e+t3vfqfExMQ636dmwcb27dtrwIABGjx4sC688EKtXLnSUZOZmalVq1bptddeU8+ePXXttdfq/fffr7e3p59+Wvn5+UpNTVWvXr1q9V1ZWdnoQ2qN8eqrr2rYsGEKCwtzjIWHh2vmzJnq0aOHBgwYIKvVqhUrVvitJ6A5shjjwcIdANBMPPbYY1qxYoV27tzZYG16erpyc3OVm5t7Xj+zR48e+u1vf6vRo0d79Lply5YpNzfX77cuAZoq9hwBgJOTJ09qy5YtWrhwoaZMmeL26x544AG1bdtWpaWljfq5lZWVuvnmm/Wzn/3Mo9e1bdtWEyZMaNTPBFA39hwBgJPs7GwtX75cN954o15++WVZrdYGX/Pll1/qzJkzkqQLL7xQLVr479+dn332mSTJarWqc+fOfvu5QFNGOAIAAHDCYTUAAAAnhCMAAAAnhCMAAAAnhCMAAAAnhCMAAAAnhCMAAAAnhCMAAAAnhCMAAAAn/x8EG9toe1Fr/QAAAABJRU5ErkJggg==ter(ullman_velocity[ullman_velocity_peaks_positive[0]], ullman_force[ullman_velocity_peaks_positive[0]],color = 'lime')
plt.xlabel(ullman_velocity_name + ' [' + ullman_velocity_unit + ']')
plt.ylabel(ullman_force_name + ' [' + ullman_force_unit + ']')
plt.show()
  Cell In[33], line 2
    plt.scatdata:image/png;base64,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RUWFHnroIaWlpSkiIkJdunTRX//6V+82ZeB3119/venevbvZtGmT2bRpk+nevbsZPnz4OV/z2WefmQ4dOpj777/ffPTRR2b//v3mX//6lzly5Iifug6cxsxXjbVr15rLL7/cJCUlmWeeeca3jQYJT+frxIkTZvDgwWblypXm448/Nps3bzZ9+/Y1vXv39mPX/rFixQrTsmVL8/zzz5s9e/aYnJwc06ZNG/Pll1/WWf/555+b1q1bm5ycHLNnzx7z/PPPm5YtW5rVq1f7ufPA8XTOcnJyzBNPPGE++OADs2/fPjNz5kzTsmVL89FHH/m588DwdL5qnDhxwlx44YVmyJAh5vLLL/dPs0GgMfM1YsQI07dvX5Ofn28OHDhg3n//ffPee+95tS/CkZ/t2bPHSDL/+c9/HGObN282kszHH39c7+vGjBljbr/9dn+0GFQaO1/GGFNUVGSSk5PNrl27TFpaWrMIR+czX84++OADI6nB/6CHmp/85CdmwoQJLmOXXHKJefDBB+usnzFjhrnkkktcxu69915z1VVX+azHYOPpnNWlW7du5pFHHvF2a0GpsfM1ZswY89vf/tY8/PDDzSoceTpfb775pomJiTHHjh3zaV8cVvOzzZs3KyYmRn379nWMXXXVVYqJidGmTZvqfE1VVZVef/11XXzxxRo6dKg6deqkvn376pVXXvFT14HTmPmSqucsKytL999/v3784x/7o9Wg0Nj5OltpaaksFovatWvngy4Do7KyUlu3btWQIUNcxocMGVLv3GzevLlW/dChQ/Xhhx/qzJkzPus1WDRmzs5WVVWl8vJydejQwRctBpXGztfSpUu1f/9+Pfzww75uMag0Zr5ee+019enTR3PnzlVycrIuvvhiTZ8+XadPn/Zqb4QjPyspKVGnTp1qjXfq1EklJSV1vubo0aM6efKkHn/8cV1//fVat26dbrrpJtlsNm3YsMHXLQdUY+ZLkp544gmFhYVpypQpvmwv6DR2vpx99913evDBBzV27NgmdWPMr7/+Wna7XfHx8S7j8fHx9c5NSUlJnfXff/+9vv76a5/1GiwaM2dne/rpp3Xq1CmNHj3aFy0GlcbM16effqoHH3xQf//73xUW1rzuBd+Y+fr888+1ceNG7dq1S2vXrtX8+fO1evVqTZo0yau9EY68ZNasWbJYLOd8fPjhh5Iki8VS6/XGmDrHpep/eUnSyJEj9etf/1o9e/bUgw8+qOHDh4fsyaG+nK+tW7dqwYIFWrZsWb01ocaX8+XszJkzuvXWW1VVVaVFixZ5/XMEg7PnoaG5qau+rvGmzNM5q7F8+XLNmjVLK1eurDO0N1XuzpfdbtfYsWP1yCOP6OKLL/ZXe0HHkz9fVVVVslgs+vvf/66f/OQn+vnPf6558+Zp2bJlXt171Lxiqg/dd999uvXWW89Zk56erh07dujIkSO1tn311Ve10nONuLg4hYWFqVu3bi7jl156qTZu3Nj4pgPIl/NVUFCgo0eP6oILLnCM2e12TZs2TfPnz9cXX3xxXr0Hgi/nq8aZM2c0evRoHThwQO+8806T2mskVf89slqttf5FevTo0XrnJiEhoc76sLAwxcbG+qzXYNGYOauxcuVKjR8/XqtWrdLgwYN92WbQ8HS+ysvL9eGHH2rbtm267777JFV/+RtjFBYWpnXr1unaa6/1S++B0Jg/X4mJiUpOTlZMTIxj7NJLL5UxRkVFReratatXeiMceUlcXJzi4uIarOvXr59KS0v1wQcf6Cc/+Ykk6f3331dpaamuvvrqOl8THh6uK6+8Up988onL+L59+5SWlnb+zQeAL+crKyur1n+Mhw4dqqysLN11113n33wA+HK+pB+C0aeffqp33323SX7xh4eHq3fv3srPz9dNN93kGM/Pz9fIkSPrfE2/fv30z3/+02Vs3bp16tOnj1q2bOnTfoNBY+ZMqt5j9Itf/ELLly/XsGHD/NFqUPB0vqKjo7Vz506XsUWLFumdd97R6tWr1blzZ5/3HEiN+fPVv39/rVq1SidPnlTbtm0lVX8XtmjRQikpKd5rzqene6NO119/venRo4fZvHmz2bx5s7nssstqXWr9ox/9yOTl5Tme5+XlmZYtW5olS5aYTz/91CxcuNBYrVZTUFDg7/b9rjHzdbbmcrWaMZ7P15kzZ8yIESNMSkqK2b59uykuLnY8KioqAvERfKbmsuEXXnjB7Nmzx+Tm5po2bdqYL774whhjzIMPPmiysrIc9TWX8v/61782e/bsMS+88EKzvZTf3Tl7+eWXTVhYmPnjH//o8mfpxIkTgfoIfuXpfJ2tuV2t5ul8lZeXm5SUFDNq1Cize/dus2HDBtO1a1fzy1/+0qt9EY4C4NixY2bcuHEmKirKREVFmXHjxpnjx4+71EgyS5cudRl74YUXzEUXXWRatWplLr/8cvPKK6/4r+kAaux8OWtO4cjT+Tpw4ICRVOfj3Xff9Xv/vvbHP/7RpKWlmfDwcHPFFVeYDRs2OLbdeeedZuDAgS7169evN7169TLh4eEmPT3dLF682M8dB54nczZw4MA6/yzdeeed/m88QDz9M+asuYUjYzyfr71795rBgwebyMhIk5KSYqZOnWq+/fZbr/ZkMea/ZxcCAACAq9UAAACcEY4AAACcEI4AAACcEI4AAACcEI4AAACcEI4AAACcEI4AAACcEI4AAACcEI4ABK309HTNnz8/aN/P+X0tFossFotOnDjh9fc/l5qf265dO7/+XKApIxwB8Lobbrih3juxb968WRaLRR999JGfu5K2bNmie+65x/HcYrHolVde8cp7P/rooyouLna5W/j5yMzM1J/+9KcG64qLi30S+IDmjHAEwOvGjx+vd955R19++WWtbX/961/Vs2dPXXHFFX7vq2PHjmrdurVP3jsqKkoJCQmyWCzn/V7ffPONNm3apBtuuKHB2oSEBK8FMgDVCEcAvG748OHq1KmTli1b5jL+7bffauXKlRo/frwkadOmTRowYIAiIyOVmpqqKVOm6NSpU/W+78GDBzVy5Ei1bdtW0dHRGj16tI4cOeJS89prr6lPnz5q1aqV4uLiZLPZHNucD6ulp6dLkm666SZZLBalp6friy++UIsWLfThhx+6vOfChQuVlpYmT25FuWzZMrVr107/+te/9KMf/UitW7fWqFGjdOrUKb344otKT09X+/btNXnyZNntdpfXvv7667r88suVnJys48ePa9y4cerYsaMiIyPVtWtXLV261O0+AHiOcATA68LCwnTHHXdo2bJlLoFi1apVqqys1Lhx47Rz504NHTpUNptNO3bs0MqVK7Vx40bdd999db6nMUY33nijvvnmG23YsEH5+fnav3+/xowZ46h5/fXXZbPZNGzYMG3btk1vv/22+vTpU+f7bdmyRZK0dOlSFRcXa8uWLUpPT9fgwYNrhY+lS5cqOzvb471C3377rZ599lmtWLFC//d//6f169fLZrPpjTfe0BtvvKGXXnpJS5Ys0erVq11e99prr2nkyJGSpN/97nfas2eP3nzzTe3du1eLFy9WXFycR30A8JABAB/Yu3evkWTeeecdx9iAAQPMbbfdZowxJisry9xzzz0urykoKDAtWrQwp0+fNsYYk5aWZp555hljjDHr1q0zVqvVHDx40FG/e/duI8l88MEHxhhj+vXrZ8aNG1dvT87vZ4wxkszatWtdalauXGnat29vvvvuO2OMMdu3bzcWi8UcOHDA7fc1xpilS5caSeazzz5zjN17772mdevWpry83DE2dOhQc++99zqef/fddyYqKsrs2LHDGGPMDTfcYO666656f3bNz4qJiTlnDQD3secIgE9ccskluvrqq/XXv/5VkrR//34VFBToF7/4hSRp69atWrZsmdq2bet4DB06VFVVVTpw4ECt99u7d69SU1OVmprqGOvWrZvatWunvXv3SpK2b9+uQYMGnVffN954o8LCwrR27VpJ1edIXXPNNY7DcJ5o3bq1unTp4ngeHx+v9PR0tW3b1mXs6NGjjufvvPOOYmNjddlll0mSfvWrX2nFihXq2bOnZsyYoU2bNjXykwFwF+EIgM+MHz9ea9asUVlZmZYuXaq0tDRHeKmqqtK9996r7du3Ox7/7//9P3366acugaKGMabOw1rO45GRkefdc3h4uLKysrR06VJVVlbq5ZdfdgQ6T7Vs2dLlucViqXOsqqrK8dz5kJok/exnP9OXX36p3NxcHT58WIMGDdL06dMb1Q8A9xCOAPjM6NGjZbVa9fLLL+vFF1/UXXfd5QgyV1xxhXbv3q2LLrqo1iM8PLzWe3Xr1k0HDx5UYWGhY2zPnj0qLS3VpZdeKknq0aOH3n77bbf7a9myZa2ToSXpl7/8pd566y0tWrRIZ86ccTmp25eMMfrnP/+pESNGuIx37NhR2dnZ+tvf/qb58+dryZIlfukHaK4IRwB8pm3bthozZox+85vf6PDhw8rOznZse+CBB7R582ZNmjRJ27dv16effqrXXntNkydPrvO9Bg8erB49emjcuHH66KOP9MEHH+iOO+7QwIEDHSddP/zww1q+fLkefvhh7d27Vzt37tTcuXPr7S89PV1vv/22SkpKdPz4ccf4pZdeqquuukoPPPCAbrvtNq/skXLH1q1bderUKQ0YMMAx9vvf/16vvvqqPvvsM+3evVv/+te/HGEQgG8QjgD41Pjx43X8+HENHjxYF1xwgWO8R48e2rBhgz799FNlZGSoV69e+t3vfqfExMQ636dmwcb27dtrwIABGjx4sC688EKtXLnSUZOZmalVq1bptddeU8+ePXXttdfq/fffr7e3p59+Wvn5+UpNTVWvXr1q9V1ZWdnoQ2qN8eqrr2rYsGEKCwtzjIWHh2vmzJnq0aOHBgwYIKvVqhUrVvitJ6A5shjjwcIdANBMPPbYY1qxYoV27tzZYG16erpyc3OVm5t7Xj+zR48e+u1vf6vRo0d79Lply5YpNzfX77cuAZoq9hwBgJOTJ09qy5YtWrhwoaZMmeL26x544AG1bdtWpaWljfq5lZWVuvnmm/Wzn/3Mo9e1bdtWEyZMaNTPBFA39hwBgJPs7GwtX75cN954o15++WVZrdYGX/Pll1/qzJkzkqQLL7xQLVr479+dn332mSTJarWqc+fOfvu5QFNGOAIAAHDCYTUAAAAnhCMAAAAnhCMAAAAnhCMAAAAnhCMAAAAnhCMAAAAnhCMAAAAnhCMAAAAn/x8EG9toe1Fr/QAAAABJRU5ErkJggg==ter(ullman_velocity[ullman_velocity_peaks_positive[0]], ullman_force[ullman_velocity_peaks_positive[0]],color = 'lime')
                                                                                                                                                                                                                                                                                                                                                           ^
SyntaxError: invalid decimal literal

Linear fitΒΆ

Well behaved dampers like this one tend to have two damping constants - one in compression and the other in rebound. Of course, these don't need to be straight lines, but in this case the shims in the damper's piston have been tuned for a linear response. Let's get a straight line fit on both these lines and see what the damping constants are:

InΒ [34]:
import numpy as np
ullman_pvp_coefficients_negative1 = np.polyfit(ullman_velocity[ullman_velocity_peaks_negative[0]], ullman_force[ullman_velocity_peaks_negative[0]],1)
ullman_pvp_negative1 = np.poly1d(ullman_pvp_coefficients_negative1)
ullman_pvp_coefficients_positive1 = np.polyfit(ullman_velocity[ullman_velocity_peaks_positive[0]], ullman_force[ullman_velocity_peaks_positive[0]],1)
ullman_pvp_positive1 = np.poly1d(ullman_pvp_coefficients_positive1)

plt.plot(ullman_velocity, ullman_pvp_negative1(ullman_velocity),color = 'red')
plt.plot(ullman_velocity, ullman_pvp_positive1(ullman_velocity),color = 'lime')
plt.text(0.2,800,'c1 = ' + str(-round(ullman_pvp_coefficients_negative1[0])) + ' N*s/m', color = 'red')
plt.text(0.2,700,'c2 = ' + str(-round(ullman_pvp_coefficients_positive1[0])) + ' N*s/m', color = 'lime')
plt.scatter(ullman_velocity[ullman_velocity_peaks_negative[0]], ullman_force[ullman_velocity_peaks_negative[0]],color = 'red')
plt.scatter(ullman_velocity[ullman_velocity_peaks_positive[0]], ullman_force[ullman_velocity_peaks_positive[0]],color = 'lime')
plt.title("Two linear fits (two damping constants)")
plt.xlabel(ullman_velocity_name + ' [' + ullman_velocity_unit + ']')
plt.ylabel(ullman_force_name + ' [' + ullman_force_unit + ']')
plt.show()
No description has been provided for this image

Higher order polynomialΒΆ

Can a single higher order polynomial fit the data?

InΒ [35]:
ullman_velocity_peaks = ullman_velocity_peaks_negative + ullman_velocity_peaks_positive
ullman_pvp_coefficients = np.polyfit(ullman_velocity[ullman_velocity_peaks[0]], ullman_force[ullman_velocity_peaks[0]],4)
ullman_pvp2 = np.poly1d(ullman_pvp_coefficients)

plt.plot(ullman_velocity, ullman_pvp2(ullman_velocity))
plt.title("4th order polynomial fit for the damping curve")
plt.scatter(ullman_velocity[ullman_velocity_peaks_negative[0]], ullman_force[ullman_velocity_peaks_negative[0]],color = 'red')
plt.scatter(ullman_velocity[ullman_velocity_peaks_positive[0]], ullman_force[ullman_velocity_peaks_positive[0]],color = 'lime')
plt.xlabel(ullman_velocity_name + ' [' + ullman_velocity_unit + ']')
plt.ylabel(ullman_force_name + ' [' + ullman_force_unit + ']')
plt.show()
No description has been provided for this image

Not in a meaningful way.

Neural network fitΒΆ

OK, let's go for a neural network fit (as shown here).

I first had to open a terminal in JupyterLab to pip install tensorflow. After that, the following script worked:

InΒ [64]:
from tensorflow import keras
import tensorflow as tf
import math

# Create the model 
model = keras.Sequential()
model.add(keras.layers.Dense(units = 1, activation = 'linear', input_shape=[1]))
model.add(keras.layers.Dense(units = 64, activation = 'relu'))
model.add(keras.layers.Dense(units = 64, activation = 'relu'))
model.add(keras.layers.Dense(units = 1, activation = 'linear'))
model.compile(loss='mse', optimizer="adam")

# Display the model
model.summary()
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/attr_value.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/tensor.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/resource_handle.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/tensor_shape.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/types.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/full_type.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/function.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/node_def.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/op_def.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/graph.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/graph_debug_info.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/versions.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/protobuf/config.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at xla/tsl/protobuf/coordination_config.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/cost_graph.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/step_stats.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/allocation_description.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/framework/tensor_description.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/protobuf/cluster.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/google/protobuf/runtime_version.py:98: UserWarning: Protobuf gencode version 5.28.3 is exactly one major version older than the runtime version 6.31.1 at tensorflow/core/protobuf/debug.proto. Please update the gencode to avoid compatibility violations in the next runtime release.
  warnings.warn(
/opt/conda/lib/python3.13/site-packages/keras/src/export/tf2onnx_lib.py:8: FutureWarning: In the future `np.object` will be defined as the corresponding NumPy scalar.
  if not hasattr(np, "object"):
/opt/conda/lib/python3.13/site-packages/keras/src/layers/core/dense.py:106: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.
  super().__init__(activity_regularizer=activity_regularizer, **kwargs)
Model: "sequential"
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Layer (type)                    ┃ Output Shape           ┃       Param # ┃
┑━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
β”‚ dense (Dense)                   β”‚ (None, 1)              β”‚             2 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ dense_1 (Dense)                 β”‚ (None, 64)             β”‚           128 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ dense_2 (Dense)                 β”‚ (None, 64)             β”‚         4,160 β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ dense_3 (Dense)                 β”‚ (None, 1)              β”‚            65 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
 Total params: 4,355 (17.01 KB)
 Trainable params: 4,355 (17.01 KB)
 Non-trainable params: 0 (0.00 B)
InΒ [65]:
# Training
model.fit( ullman_velocity, ullman_force, epochs=100, verbose=1)
Epoch 1/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 3s 1ms/step - loss: 13814.1543
Epoch 2/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 2722.0652
Epoch 3/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 2207.5793
Epoch 4/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1749.1078
Epoch 5/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1529.4952
Epoch 6/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1440.0519
Epoch 7/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1392.2977
Epoch 8/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1363.6760
Epoch 9/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1349.8647
Epoch 10/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1341.4752
Epoch 11/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1327.3407
Epoch 12/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1325.1079
Epoch 13/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1314.2338
Epoch 14/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1308.0569
Epoch 15/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1308.1688
Epoch 16/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1304.6078
Epoch 17/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1303.7666
Epoch 18/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1305.5067
Epoch 19/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1303.3816
Epoch 20/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1303.4846
Epoch 21/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1297.2653
Epoch 22/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1294.5061
Epoch 23/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1296.4343
Epoch 24/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1294.7406
Epoch 25/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1298.7593
Epoch 26/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1297.2434
Epoch 27/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1296.7106
Epoch 28/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1296.0599
Epoch 29/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1295.3154
Epoch 30/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1295.5212
Epoch 31/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1296.8688
Epoch 32/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1294.0133
Epoch 33/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.4882
Epoch 34/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1293.6497
Epoch 35/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.7628
Epoch 36/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1293.1870
Epoch 37/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1294.5201
Epoch 38/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.2454
Epoch 39/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.5138
Epoch 40/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.5327
Epoch 41/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1293.0852
Epoch 42/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1295.9518
Epoch 43/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.1375
Epoch 44/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1291.6090
Epoch 45/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1291.8464
Epoch 46/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1294.0609
Epoch 47/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.8826
Epoch 48/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.3689
Epoch 49/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.6859
Epoch 50/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.2965
Epoch 51/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1288.2144
Epoch 52/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.1262
Epoch 53/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.8053
Epoch 54/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.2422
Epoch 55/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.0076
Epoch 56/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1291.0084
Epoch 57/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1291.6095
Epoch 58/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1288.3645
Epoch 59/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.5881
Epoch 60/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1294.8358
Epoch 61/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.7021
Epoch 62/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.0344
Epoch 63/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.0354
Epoch 64/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.5771
Epoch 65/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.5732
Epoch 66/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.8263
Epoch 67/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1285.4114
Epoch 68/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.3972
Epoch 69/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.7135
Epoch 70/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.1635
Epoch 71/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.6438
Epoch 72/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.3409
Epoch 73/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.9170
Epoch 74/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.0470
Epoch 75/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1288.8875
Epoch 76/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.4871
Epoch 77/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1285.6396
Epoch 78/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.5902
Epoch 79/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1288.8912
Epoch 80/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1288.1246
Epoch 81/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.0289
Epoch 82/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.7023
Epoch 83/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1291.7206
Epoch 84/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1286.4290
Epoch 85/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1285.0483
Epoch 86/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1291.2622
Epoch 87/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.9436
Epoch 88/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1290.9926
Epoch 89/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.3160
Epoch 90/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1283.1725
Epoch 91/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1292.7914
Epoch 92/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1287.0483
Epoch 93/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1284.6010
Epoch 94/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.8257
Epoch 95/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.7552
Epoch 96/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.2177
Epoch 97/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1289.0544
Epoch 98/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1286.4901
Epoch 99/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1286.8035
Epoch 100/100
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 1ms/step - loss: 1284.6512
Out[65]:
<keras.src.callbacks.history.History at 0xe8020c285be0>
InΒ [66]:
# Compute the output 
ullman_force_predicted = model.predict(ullman_velocity)

# Display the result
plt.scatter(ullman_velocity,ullman_force)
plt.plot(ullman_velocity, ullman_force_predicted, 'r', linewidth=4)
plt.title("100 epoch neural network fit with TensorFlow")
plt.xlabel(ullman_velocity_name + ' [' + ullman_velocity_unit + ']')
plt.ylabel(ullman_force_name + ' [' + ullman_force_unit + ']')
# plt.grid()
plt.show()
1064/1064 ━━━━━━━━━━━━━━━━━━━━ 1s 750us/step
No description has been provided for this image