EGR 103/Fall 2023/Lab 2
Contents
- 1 Introduction
- 2 Errors / Additions
- 3 2.1 Introduction
- 4 2.2 Resources
- 5 2.3 Console and Script Overview
- 6 2.4 Cantilever Beam Analysis
- 7 2.5 Creating the Script
- 7.1 2.5.1 Lab Manual Syntax
- 7.2 2.5.2 Comments
- 7.3 2.5.3 Importing Modules
- 7.4 2.5.4 Loading and Manipulating the Data
- 7.5 2.5.5 Plotting
- 7.6 2.5.6 Polynomials in NumPy
- 7.7 2.5.7 Better Printing
- 7.8 2.5.8 Calculate Model Values
- 7.9 2.5.9 Generating Plots (revisited)
- 7.10 2.5.10 Saving Plots
- 7.11 2.5.11 Generating Plots (revisited*2)
- 8 2.6 The Assignment
- 9 2.7 Code From Lab
Introduction
Among other things, you will learn how to use Spyder as well as how to upload assignments for EGR 103.
Errors / Additions
- None yet!
2.1 Introduction
The main purpose of this lab is to go through the process of writing a complete program to load a data set, manipulate the values, perform some analysis, and create a graph. The following is a companion piece to the lab handout itself. The sections in this guide will match those in the handout.
2.2 Resources
You will want to have a browser open with at least the Python:Script and Python:Plotting pages available to you. You will also want to go through all the steps in EGR 103/Spring 2023/Beginning of Lab right when you get into the lab room. If you have any issues with those steps, let a TA know as soon as possible to get help. These steps will get the files you need in the places you need them and then will get Spyder ready to go.
2.3 Console and Script Overview
Take a look at the Python page for some demonstrations on using the console and scripts. Note that the first time you run a script, Spyder will bring up a dialog box about how you would like to run scripts. The defaults are all good and you do not need to see that dialog box again, so just click the Run button.
2.4 Cantilever Beam Analysis
Read and work through this section, taking notes as you go. Note especially the process of rearranging the equation to get displacement as a function of force based on the fact that - for this experiment - the independent variable is the force.
To see the data set, make sure Spyder is looking at the correct directory (it should be pointed at your Lab02Files folder on Box), then click the File tab at the bottom of the information panel (the one above the console window). Double-click the Cantilever.dat
file and Spyder will open it in the text editor. You will see an 8x2 array of data. The first column of numbers is the amount of mass in kg placed on the end of the beam - for this experiment, it ranged from 0 to about 0.8 kg (i.e. about 8 N). The second column of numbers is the displacement measured in inches, because that is what the device I used measured in. You should always take data in the original units of the device; you can convert it later.
Typically, data sets should have descriptions such as the items in the data set, units, perhaps the equipment used, and the person who took the measurements. For this week, however, I wanted to give you an array of data that Python can easily load. Later in the course, we will see more sophisticated ways of loading annotated data sets.
2.5 Creating the Script
Note when you open a second script that there are tabs in the editing window; you can choose which one to make active by clicking its tab. Be careful not to accidentally click the part of the tab that closes that tab (the X).
Make sure you are saving the run_can.py script in your Lab02Files folder on Box! If you don't you will get an error that Spyder can't find Cantilever.dat.
2.5.1 Lab Manual Syntax
For this lab, there will be several times you will simply type some items into the command window to see what they do before actually adding codes to the script. Command-line only items are surrounded by a box whereas code that goes in the script has a shadowbox.
2.5.2 Comments
While you are not explicitly required to include comments in your labs -- other than the header and community standard information at the top -- comments are a great way to tell yourself and your TAs what you meant to do with particular chunks of code. Also, note that a line starting with # %%
will set off a section in the editor window. It will have no effect on the way the program runs, just what it looks like in your editing window. By creating cells that way, you can also run your code one cell at a time.
2.5.3 Importing Modules
Code lines 1-3
Read and work through this section, taking notes as you go. These lines will import two modules with nicknames. If you want to see what a module has in it, once imported, type help(NAME) - for instance,
help(np)
will show everything in np. If you want help on a particular command, put the command in the argument - for instance,
help(plt.plot)
2.5.4 Loading and Manipulating the Data
Code lines 5-14
Read and work through this section, taking notes as you go. Note that when you slice arrays, you need to append the .copy() to duplicate the data rather than have two different variables pointing at the same data.
2.5.5 Plotting
Code lines 27-32 (note the big skip here; we'll fill that in later)
Read and work through this section, taking notes as you go. You may also want to check out Python:Plotting and specifically the simple examples at the top of the page.
Note that the code for this will end up several lines under what you've written so far; you will be filling in the blank space later. Also - as will be described in the lab, there are a few different ways to make plots. During the lab, you will change the preferences in Spyder to create graphics using the "Automatic" backend instead of "Inline". This generally means that figures will be in their own window instead of in the console window. To make this change in Spyder:
- Open the preferences window
- On Windows, go to the Tools menu near the top right of the window and select Preferences
- On MACs, go to the python menu near the top left of the window and select Preferences
- In the Preferences window at the left select IPython console
- In the right half of the Preferences window, select the Graphics tab
- In the Backend pulldown, select Automatic
- Click OK in the Preferences window
This change will take effect the next time you start Spyder. To make it take effect now, you need to restart the kernel. Go to the settings icon at the top right of the console (the gear or three horizontal lines), click it, and Restart kernel. Note that this will clear all variables and loaded modules as well. Re-run your script to see the figure in its own window.
2.5.6 Polynomials in NumPy
Code lines 16-19 (note that this goes before plotting)
Read and work through this section, taking notes as you go. Be sure you understand how Python - using NumPy - interprets polynomials and which commands use them.
2.5.7 Better Printing
Re-code line 19
Read and work through this section, taking notes as you go. This will specifically have you change line 19 to have the values displayed in a more useful format.
2.5.8 Calculate Model Values
Code lines 21-25 (after this, no more gap between plotting code and the rest of the code)
Read and work through this section, taking notes as you go. This part creates a new set of data points based on your equation so that you can actually plot it. You will thus have your original eight data points in force
and disp
. You will also have 100 linearly spaced values between the minimum and maximum force value in force_model
and the 100 calculated estimates for the displacement, based on your best straight line, in disp_model
.
2.5.9 Generating Plots (revisited)
Code lines 33-34
Read and work through this section, taking notes as you go. This part adds the new line to your old graph.
2.5.10 Saving Plots
Code lines 45-46 (note the big skip here)
CRITICALLY IMPORTANT PART - never put .py in a savefig argument! Your graph might override your program!
OTHER CRITICALLY IMPORTANT PART - saving the graphs needs to happen after you have done all the things you want to the graphs. Even though you may have typed this code before typing the code for labels, this code will end up at the bottom of your script! See the full code below to figure out how things should be arranged.
2.5.11 Generating Plots (revisited*2)
Code lines 35-44 (gap in code is now gone)
Read and work through this section, taking notes as you go. This part adds useful parts to your graph and makes it take up space more efficiently.
2.6 The Assignment
Basically, once you get this script running perfectly, you are going to replicate it three times and change it to use three different data sets. Note: these three data sets are "cooked" - that is, I produced them; they did not come from an experiment. Some of them will not look like they came from a cantilever beam experiment, because they did not come from a cantilever beam experiment.
2.6.1 What the .py-files Should Do
Read and work through this section, taking notes as you go. All the data sets are text files with numbers separated by tabs.
2.6.2 The Lab Report
Read and work through this section, taking notes as you go. Note that the data sets have different numbers of points so the bottoms of the data tables will not line up. Also, note that you should use the original data (masses and displacements in inches) in the tables -- do not put in the forces or the displacements in meters. You are using the latter in your calculations but you are presenting the original data sets here.
Here is the code for getting the beam_data numbers to show up on the screen in a way that is easy to copy to your tex file:
for a in range(beam_data.size // 2):
print(
"{:0.4e} & {:0.4e} \\\\".format(
beam_data.iloc[a, 0], beam_data[a, 1]
)
)
If you choose to add this to your script - you are certainly welcome to leave it in there when you turn your code in.
2.6.3 Checking Your Work
Seriously - check spelling!
2.7 Code From Lab
Here's a Trinket version:
Chrome seems to work well for copying and pasting from line-numbered codes on Pundit. Some other browsers? Not so much...
1 # %% Import modules
2 import numpy as np
3 import matplotlib.pyplot as plt
4
5 # %% Load and manipulate the data
6 # Load data from Cantilever.dat
7 beam_data = np.loadtxt("Cantilever.dat")
8 # Copy data from each column into new variables
9 mass = beam_data[:, 0].copy()
10 disp = beam_data[:, 1].copy()
11 # Convert mass to a force measurement
12 force = mass * 9.81
13 # Convert displacement to meters
14 disp = (disp * 2.54) / 100.0
15
16 # %% Perform calculations
17 # Use polyfit to find first-order fit polynomials
18 p = np.polyfit(force, disp, 1)
19 print('{:0.4e} {:0.4e}'.format(*p))
20
21 # %% Generate predictions
22 # Create 100 representational force values
23 force_model = np.linspace(force.min(), force.max(), 100)
24 # Calculate displacement predictions
25 disp_model = np.polyval(p, force_model)
26
27 # %% Generate and save plots
28 # Create a Figure and Axes
29 fig = plt.figure(num=1, clear=True)
30 ax = fig.add_subplot(1, 1, 1)
31 # Plot Displacement as a function of Force
32 ax.plot(force, disp, "ko")
33 # Plot the model values
34 ax.plot(force_model, disp_model, "b-")
35 # Turn the grid on
36 ax.grid(True)
37 # Label and title the graph
38 ax.set(
39 xlabel="Force (Newtons)",
40 ylabel="Displacement (meters)",
41 title="Displacement vs. Force for Cantilever.dat (NetID)",
42 )
43 # Use tight layout
44 fig.tight_layout()
45 # Save the graph as a PNG file
46 fig.savefig("RunCanPlot.png")