<jupyter_start><jupyter_text>Plotting a trajectory of a particle[Here](http://hyperphysics.phy-astr.gsu.edu/hbase/mot.html) is a link to the Hyperphysics section of kinematics, we will be coding up these equations.[Here](https://www.khanacademy.org/science/physics/one-dimensional-motion/kinematic-formulas/a/what-are-the-kinematic-formulas) is a link to the derivation of those equations, also worth a read to brush up on your kinematics. First, we will import the two libraries we used earlier, Numpy and Matplotlib. These will let us do some basic maths, and set up our plot.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>We will then set up some initial parameters. We are going to simulate a projectile launched from the ground at an angle and plot the trajectory. We will define everything in separate 'x' and 'y' dimensions, and simply sum the results.Firstly, we define the acceleration due to gravity in the x and y direction in units of m/s^2:<jupyter_code>a_x = 0
a_y = -9.81 # note the sign of acceleration is downwards<jupyter_output><empty_output><jupyter_text>Now we will choose an initial velocity in m/s, and an angle we want to launch the projectile from in degrees:<jupyter_code>v_i = 100
angle = 60<jupyter_output><empty_output><jupyter_text>Next, we break down this velocity into an x and  y component using trigonometry. Take a look at the figure below and check that you can see the equations in Python matching those in the plot:![alt text](https://i.imgur.com/uks7IpN.png)Here is where we call `Numpy`, note that `np.sin(angle)` will assume the angle is in radians but we defined *our* angle in degrees. Luckily `Numpy` *also* has a function to convert degrees into radians called `np.deg2rad(angle)`.Putting these two functions together:**Note:** When presented with nested brackets, Python will start on the inside and work outwards.<jupyter_code>v_ix = v_i * np.cos(np.deg2rad(angle))
v_iy = v_i * np.sin(np.deg2rad(angle))<jupyter_output><empty_output><jupyter_text>We now need to create a list of points, or timestamps, at which to calculate the x/y position of the projectile as time passes.We work out how long the projectile will fly for in seconds before it hits the ground (`t_max`), and create a list of interval size `t_step` between 0 and that time.Using the time-of-flight equation: ![alt text](https://i.imgur.com/4ocn4aU.png)<jupyter_code>t_max = 2 * v_i * np.sin(np.deg2rad(angle)) / -a_y
t_step = 0.01
timestamps = np.arange(0, t_max, t_step)<jupyter_output><empty_output><jupyter_text>Now, we take those time stamps and plug them into the equation below (once for x and once for y) along with our inital conditions:![alt text](https://i.imgur.com/krbihbA.png)<jupyter_code>x = v_ix * timestamps + 0.5 * a_x * timestamps**2 
y = v_iy * timestamps + 0.5 * a_y * timestamps**2<jupyter_output><empty_output><jupyter_text>Lastly, we set up a plot like in the introductory Notebook and plot our results!<jupyter_code>fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()<jupyter_output><empty_output><jupyter_text>The entire script together is shown below. I've added extra comments to remind us what is going on, this is good practice for when we start writing more complicated code! I've also added a few extra lines in the plotting part to make our plot look nicer.The curly brackets `{}` in the `plt.title()` line is a way to tell Python to expect some formatting after the string, in this case we want to insert the value of `angle` in the title.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt

# set up intial conditions, all SI units
a_x = 0
a_y = -9.81 # note the sign of acceleration is downwards

v_i = 100
angle = 45

# work out initial velocities in x/y
v_ix = v_i * np.cos(np.deg2rad(angle))
v_iy = v_i * np.sin(np.deg2rad(angle))

# set up a list of timestamps to evaluate the velocity
t_max = 2 * v_i * np.sin(np.deg2rad(angle)) / -a_y
t_step = 0.01
timestamps = np.arange(0, t_max, t_step)

# use kinematic equation to work out the x and y velocities
x = v_ix * timestamps + (0.5 * a_x * timestamps**2)
y = v_iy * timestamps + (0.5 * a_y * timestamps**2)

# plot the results!
fig, ax = plt.subplots()
ax.plot(x, y)
plt.xlabel('Distance / m')
plt.ylabel('Height / m')
plt.title('The trajectory of a particle launched at {} degrees'.format(angle))
plt.show()<jupyter_output><empty_output><jupyter_text>Multiple ProjectilesLets say we wanted to measure the distance our projectile travelled for a variety of starting conditions such as various angles, heights, gravity, or initial velocities.We *could* simply run the code over and over and manually change the code each time ... but we can do better than that. Plus it would be nice to plot all the results at once for easy comparison.Here's how we can adapt the above code to plot a few different angles at once. I'll also save the maximum distance for each angle, and print the results.As before I'll go through the bits of code one at a time, and then put it all together. It's very similar to the previous example but we're adding a loop so we can plot a few trajectories on one graph. As before, we'll start with some imports:<jupyter_code>import numpy as np
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>We then define some physical values for our initial conditions:<jupyter_code>v_i = 100
a_x = 0
a_y = -9.81<jupyter_output><empty_output><jupyter_text>Now for the angles. Before we had a single value, this time we're going to create a list of angles to use. We will use `np.arange()` which creates evenly spaced values between two numbers at a given interval. In this case we start at 0 degrees and end at 90 degrees in intervals of 10. See [here](https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.arange.html) for more information.<jupyter_code>angles = np.arange(0,90,10)

print (angles)<jupyter_output><empty_output><jupyter_text>Now for the loop. Last time we simply called the equations for our initial conditions along with the timestamps and created the single plot.*This* time we're going to loop through each value of angle, and create a plot for each one and add it to the graph. Because this is a loop, we can't break it up into multiple cells, but I've added a lot of comments to help understand each line.<jupyter_code># lets loop through each of those angle values and work out the trajectory
for i in range(len(angles)):
    
    # each projectile gets a unique set of timestamps, so that each trajectory curve has 100 samples
    t_max = 2 * v_i * np.sin(np.deg2rad(angles[i])) / -a_y
    t_step = 0.01
    timestamps = np.arange(0, t_max, t_step)
    
    # we then work out the x/y coordinates of our projectile at each timestamp
    # this is identical as before, but this time we're just picking the i-th angle from the list we made earlier
    x = v_i * timestamps * np.cos(np.deg2rad(angles[i])) + (0.5 * a_x * timestamps**2)
    y = v_i * timestamps * np.sin(np.deg2rad(angles[i])) + (0.5 * a_y * timestamps**2)
    
    # add that data to the plot, give it a label
    plt.plot(x, y, label = angles[i])
    # the loop will now repeat for the next angle until we reach the last angle
    
plt.legend()
plt.xlabel('Distance / m')
plt.ylabel('Height / m')
plt.title('The trajectory of a particle launched at various angles')
plt.xlim((0,1200))
plt.show()<jupyter_output><empty_output><jupyter_text>You might think that the last line in the loop above will show a new plot each time in the loop, but it simply means 'add this data to the plot'.We then overwrite the values of `x` and `y` in the next loop iteration for the next angle, and add *that* new data to the plot. Then in the end we plot all the data together.You may also have noticed the extra bit of code `label = angles[i]`. This gives each line a label, in this case the angle, and we can add these labels to the plot later.Once the loop is finished we can finally show the plot on the screen with `plt.show()`. I've also added a few extra formatting things like axis labels and a title like before. The `matplotlib` library is clever and auto asigns a new colour to each plot for us.The line `plt.legend()` simply turns on the legend, and it will display the labels we assigned earlier. Also as before, I've put everything together in one cell and deleted some of the comments:<jupyter_code>v_i = 100 
a_y = -9.81
a_x = 0

angles = np.arange(0,90,10)

# create an empty array, we'll save a value here for each projectile
max_distance = []

# lets loop through each of those angle values and work out the trajectory
for i in range(len(angles)):
    
    # each projectile gets a unique set of timestamps, so that each one is sampled 100 times
    t_max = 2 * v_i * np.sin(np.deg2rad(angles[i])) / -a_y
    t_step = 0.01
    timestamps = np.arange(0, t_max, t_step)
    
    # we then work out the x/y coordinates of our projectile at each timestamp for that angle
    x = v_i * timestamps * np.cos(np.deg2rad(angles[i])) + (0.5 * a_x * timestamps ** 2)
    y = v_i * timestamps * np.sin(np.deg2rad(angles[i])) + (0.5 * a_y * timestamps ** 2)
    
    # this little 'if' loop will take the last x=position of each projectile so we can compare how far they landed
    # BUT, the 1st angle is 0 degrees and doesn't go anyway, so I need to explcity put a '0' as the 1st value in 'max_distances'
    # for all the rest I can just take the last item in the list of x-distances with x[-1]
    # 'append' just means add the end of the list
    if angles[i] == 0:
        max_distance.append(0)
    else:
        max_distance.append(x[-1])
    
    # add that data to the plot, give it a label
    plt.plot(x, y, label = angles[i])


plt.legend()
plt.xlabel('Distance / m')
plt.ylabel('Height / m')
plt.title('The trajectory of a particle launched at various angles')
plt.xlim((0,1200))
plt.show()<jupyter_output><empty_output><jupyter_text>Lastly, remember we saved how far each projectile went? We can print these results here by looping through that array:<jupyter_code># print a statement by looping through the list of angles and max_distances
# we also use another Numpy function to round the distance value to 2 dp for neatness
for i in range(len(angles)):
    print ('Projectile launched at {a} degrees reached {b} meters'.format(a=angles[i], b=np.round(max_distance[i],2)))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08534946236559139, 'fraction_numerical': 0.013344854070660522, 'mean_word_length': 4.309378185524975, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 57, 'https://': 5, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '14', 'dir': 'jupyter-structured-clean-dedup', 'id': '495851', 'license': 'MIT', 'n_tokens_mistral': 3388, 'n_tokens_neox': 3220, 'n_words': 1435, 'path': "particle-physcis'/plotting a  trajectory of a particle.ipynb", 'repo_name': 'PulsatingGenius/coding-for--physics', 'size': '10416'}