Difference between revisions of "User:DukeEgr93/CBApp"
Jump to navigation
Jump to search
Line 1: | Line 1: | ||
Steps: | Steps: | ||
− | + | == Select a set and load data == | |
− | + | * Add a button and have it simply load Beam01.dat | |
− | + | :* Drag button onto app | |
− | + | :* Change text to Run | |
− | + | :* Since data set will likely be needed in various parts of app, in the Code View, add a public property called Force and a public property called Displacement: | |
− | + | ::<source lang=MATLAB> | |
properties (Access = public) | properties (Access = public) | ||
Force % Force applied to beam | Force % Force applied to beam | ||
Disp % Displacement measured at end | Disp % Displacement measured at end | ||
end</source> | end</source> | ||
− | + | :* In component browser, right click app.RunButton and add a RunButtonPushed callback | |
− | + | :* Add code in this to load the data, split it, and put it into appropriate variables: | |
− | + | ::<source lang=MATLAB> | |
function RunButtonPushed(app, event) | function RunButtonPushed(app, event) | ||
Data = load('Beam01.dat'); | Data = load('Beam01.dat'); | ||
Line 18: | Line 18: | ||
app.Disp = 0.0254 * Data(:,2); | app.Disp = 0.0254 * Data(:,2); | ||
end</source> | end</source> | ||
− | + | :* Check this by putting a keyboard in the RunButtonPushed callback; run the app and at the keyboard prompt, see what Data, app.Force, and app.Displ look like. Use dbquit to get out of keyboard and if all is good, delete the keyboard command: | |
− | + | ::<source lang=MATLAB> | |
function RunButtonPushed(app, event) | function RunButtonPushed(app, event) | ||
Data = load('Beam01.dat'); | Data = load('Beam01.dat'); | ||
Line 27: | Line 27: | ||
end | end | ||
</source> | </source> | ||
− | + | ::Results:<source lang=MATLAB> | |
K>> Data | K>> Data | ||
Line 69: | Line 69: | ||
K>> dbquit | K>> dbquit | ||
</source> | </source> | ||
− | + | == Plot the data == | |
− | + | * Go into Design View and add a set of axes | |
− | + | :* Change the axis labels and titles as needed | |
− | + | * Go into the Code View and add code to the RunButtonPushed function to plot the data and add a grid | |
− | + | :<source lang=MATLAB> | |
function RunButtonPushed(app, event) | function RunButtonPushed(app, event) | ||
Data = load('Beam01.dat'); | Data = load('Beam01.dat'); | ||
Line 105: | Line 105: | ||
end | end | ||
</source> | </source> | ||
− | + | == Calculate and plot fit == | |
− | + | Next we will hard-code a first-order fit; later, we will make the code flexible for higher order fits. | |
− | + | * In Design View, add a spinner and call it Order | |
− | + | :* Click on app.OrderSpinner in the Component Browser; in the Spinner Properties - Configuration, change the minimum value to 0 and change the Display to Integers. | |
− | + | * You will most likely need to calculate the goodness of fit either when you click the Run button or when you change the spinner. This means it would be a good idea to make a separate function that calculates the fit; the callbacks for both the button and the spinner can then call this new function. | |
− | + | * In the Code View, make a new public function called CalcFit | |
+ | :<source lang=MATLAB> | ||
function results = CalcFit(app) | function results = CalcFit(app) | ||
end | end | ||
</source> | </source> | ||
− | + | * Various parts of the app will probably need to know the coefficients of the fit, so add a public property called Coefs. | |
− | + | :<source lang=MATLAB> | |
properties (Access = public) | properties (Access = public) | ||
Force % Force applied to beam | Force % Force applied to beam | ||
Line 123: | Line 124: | ||
end | end | ||
</source> | </source> | ||
− | + | * Add code to the CalcFit program that uses the value in the Order spinner to determine the coefficients of a fit of that order: | |
− | + | :<source lang=MATLAB> | |
function results = CalcFit(app) | function results = CalcFit(app) | ||
app.Coefs = polyfit(app.Force, app.Disp, app.OrderSpinner.Value); | app.Coefs = polyfit(app.Force, app.Disp, app.OrderSpinner.Value); | ||
end | end | ||
</source> | </source> | ||
− | + | * Add a changed callback to the OrderSpinner to update the plot when the spinner value changes: | |
− | + | :<source lang=MATLAB> | |
function OrderSpinnerValueChanged(app, event) | function OrderSpinnerValueChanged(app, event) | ||
UpdatePlot(app); | UpdatePlot(app); | ||
end | end | ||
</source> | </source> | ||
− | + | * Add code to the UpdatePlot function to get the new coefficients and use them to plot a model: | |
− | + | :<source lang=MATLAB> | |
function results = UpdatePlot(app) | function results = UpdatePlot(app) | ||
plot(app.UIAxes, app.Force, app.Disp, 'ko') | plot(app.UIAxes, app.Force, app.Disp, 'ko') | ||
Line 149: | Line 150: | ||
end | end | ||
</source> | </source> | ||
+ | == Determine and display statistics == | ||
+ | Once again, determining and displaying statistics will be triggered by multiple events (hitting the button or changing the order) so there might as well be a function for it that various callbacks can use. | ||
+ | * In the Code View, create a public function called CalcStats | ||
+ | * Add code to CalcStats to calculate the coefficient of determination for the fit; leave the semi-colons off for now so you can see these values in the command window and see if they make sense. | ||
+ | <source lang=MATLAB> | ||
+ | function results = CalcStats(app) | ||
+ | Dbar = mean(app.Disp); | ||
+ | Dhat = polyval(app.Coefs, app.Force); | ||
+ | St = sum((app.Disp-Dbar).^2) | ||
+ | Sr = sum((app.Disp-Dhat).^2) | ||
+ | r2 = (St-Sr) / St | ||
+ | end | ||
+ | </source> | ||
+ | * Add code to the end of the callbacks for the button and the spinner to run this function: | ||
+ | <source lang=MATLAB> | ||
+ | % Button pushed function: RunButton | ||
+ | function RunButtonPushed(app, event) | ||
+ | Data = load('Beam01.dat'); | ||
+ | app.Force = 9.81 * Data(:,1); | ||
+ | app.Disp = 0.0254 * Data(:,2); | ||
+ | UpdatePlot(app); | ||
+ | CalcStats(app); | ||
+ | end | ||
+ | |||
+ | % Value changed function: OrderSpinner | ||
+ | function OrderSpinnerValueChanged(app, event) | ||
+ | UpdatePlot(app); | ||
+ | CalcStats(app); | ||
+ | end | ||
+ | </source> | ||
+ | * Test your code - for this data set, note that r2 for a 0 order fit is always 0; r2 for 6th order is almost exactly 1 and r2 for a 7th order fit is exactly 1. If your code is working at this point - congratulations! If not - go ahead and figure out how to fix it before moving on. | ||
+ | == Display stats in a table == | ||
+ | Now you are going to add a table to your app to display information about the number of points, order of fit, St, Sr, and r2 value. | ||
+ | * In the Design View, drag a Table in. | ||
+ | * There will be five columns named NumPts, Order, St, Sr, r2 -- make these changes in the Names dropdown in the Columns section of the Configuration block in the UITABLE PROPERTIES menu (whew!). | ||
+ | * Make the table wide enough to see all five columns. | ||
+ | * Go to the CodeView. Think about where it would make the most sense to update the table values. CalcStats is where the information will be calculated, so this is probably the right function to also update the table. | ||
+ | :* In the CalcStats function, add a line that will load the appropriate information into app.UITable.Data: | ||
+ | <source lang=MATLAB> | ||
+ | function results = CalcStats(app) | ||
+ | Dbar = mean(app.Disp); | ||
+ | Dhat = polyval(app.Coefs, app.Force); | ||
+ | St = sum((app.Disp-Dbar).^2); | ||
+ | Sr = sum((app.Disp-Dhat).^2); | ||
+ | r2 = (St-Sr) / St; | ||
+ | app.UITable.Data = [length(app.Force), app.OrderSpinner.Value, St, Sr, r2]; | ||
+ | end | ||
+ | </source> | ||
+ | * The table is clearly too tall - in the Design View, you can shrink the table to make the size make sense for the number of rows (1) you have. |
Revision as of 02:08, 1 April 2018
Steps:
Contents
Select a set and load data
- Add a button and have it simply load Beam01.dat
- Drag button onto app
- Change text to Run
- Since data set will likely be needed in various parts of app, in the Code View, add a public property called Force and a public property called Displacement:
properties (Access = public) Force % Force applied to beam Disp % Displacement measured at end end
- In component browser, right click app.RunButton and add a RunButtonPushed callback
- Add code in this to load the data, split it, and put it into appropriate variables:
function RunButtonPushed(app, event) Data = load('Beam01.dat'); app.Force = 9.81 * Data(:,1); app.Disp = 0.0254 * Data(:,2); end
- Check this by putting a keyboard in the RunButtonPushed callback; run the app and at the keyboard prompt, see what Data, app.Force, and app.Displ look like. Use dbquit to get out of keyboard and if all is good, delete the keyboard command:
function RunButtonPushed(app, event) Data = load('Beam01.dat'); app.Force = 9.81 * Data(:,1); app.Disp = 0.0254 * Data(:,2); keyboard end
- Results:
K>> Data Data = 0 0.0052 0.1135 0.1587 0.2273 0.3140 0.3408 0.4746 0.4558 0.6368 0.5693 0.7799 0.6836 0.9366 0.7971 1.0000 K>> app.Force ans = 0 1.1135 2.2296 3.3431 4.4715 5.5850 6.7064 7.8199 K>> app.Disp ans = 0.0001 0.0040 0.0080 0.0121 0.0162 0.0198 0.0238 0.0254 K>> dbquit
Plot the data
- Go into Design View and add a set of axes
- Change the axis labels and titles as needed
- Go into the Code View and add code to the RunButtonPushed function to plot the data and add a grid
function RunButtonPushed(app, event) Data = load('Beam01.dat'); app.Force = 9.81 * Data(:,1); app.Disp = 0.0254 * Data(:,2); plot(app.UIAxes, app.Force, app.Disp, 'ko') grid(app.UIAxes, 'on') end
- At this point, it would be good to take a moment to think about what processes this app will need to access based on making changes to various fields. Later, we are going to add the ability to fit the model with a polynomial of different orders, and as we change the order of the fit, we will probably also want the graph to update. Given that, it might be better to have a process to plot things that is separate from pushing the button.
- In Code View, add a new public function and call it UpdatePlot
function results = UpdatePlot(app) end
- Cut the plotting code from the RunButtonPushed function and paste it into the UpdatePlot function:
function results = UpdatePlot(app) plot(app.UIAxes, app.Force, app.Disp, 'ko') grid(app.UIAxes, 'on') end
- Add a call to the UpdatePlot function at the end of the RunButtonPushed function:
function RunButtonPushed(app, event) Data = load('Beam01.dat'); app.Force = 9.81 * Data(:,1); app.Disp = 0.0254 * Data(:,2); UpdatePlot(app); end
Calculate and plot fit
Next we will hard-code a first-order fit; later, we will make the code flexible for higher order fits.
- In Design View, add a spinner and call it Order
- Click on app.OrderSpinner in the Component Browser; in the Spinner Properties - Configuration, change the minimum value to 0 and change the Display to Integers.
- You will most likely need to calculate the goodness of fit either when you click the Run button or when you change the spinner. This means it would be a good idea to make a separate function that calculates the fit; the callbacks for both the button and the spinner can then call this new function.
- In the Code View, make a new public function called CalcFit
function results = CalcFit(app) end
- Various parts of the app will probably need to know the coefficients of the fit, so add a public property called Coefs.
properties (Access = public) Force % Force applied to beam Disp % Displacement measured at end Coefs % Fit coefficients end
- Add code to the CalcFit program that uses the value in the Order spinner to determine the coefficients of a fit of that order:
function results = CalcFit(app) app.Coefs = polyfit(app.Force, app.Disp, app.OrderSpinner.Value); end
- Add a changed callback to the OrderSpinner to update the plot when the spinner value changes:
function OrderSpinnerValueChanged(app, event) UpdatePlot(app); end
- Add code to the UpdatePlot function to get the new coefficients and use them to plot a model:
function results = UpdatePlot(app) plot(app.UIAxes, app.Force, app.Disp, 'ko') grid(app.UIAxes, 'on') CalcFit(app); FModel = linspace(min(app.Force), max(app.Force), 100); DModel = polyval(app.Coefs, FModel); hold(app.UIAxes, 'on') plot(app.UIAxes, FModel, DModel, 'k-') hold(app.UIAxes, 'off') keyboard end
Determine and display statistics
Once again, determining and displaying statistics will be triggered by multiple events (hitting the button or changing the order) so there might as well be a function for it that various callbacks can use.
- In the Code View, create a public function called CalcStats
- Add code to CalcStats to calculate the coefficient of determination for the fit; leave the semi-colons off for now so you can see these values in the command window and see if they make sense.
function results = CalcStats(app)
Dbar = mean(app.Disp);
Dhat = polyval(app.Coefs, app.Force);
St = sum((app.Disp-Dbar).^2)
Sr = sum((app.Disp-Dhat).^2)
r2 = (St-Sr) / St
end
- Add code to the end of the callbacks for the button and the spinner to run this function:
% Button pushed function: RunButton
function RunButtonPushed(app, event)
Data = load('Beam01.dat');
app.Force = 9.81 * Data(:,1);
app.Disp = 0.0254 * Data(:,2);
UpdatePlot(app);
CalcStats(app);
end
% Value changed function: OrderSpinner
function OrderSpinnerValueChanged(app, event)
UpdatePlot(app);
CalcStats(app);
end
- Test your code - for this data set, note that r2 for a 0 order fit is always 0; r2 for 6th order is almost exactly 1 and r2 for a 7th order fit is exactly 1. If your code is working at this point - congratulations! If not - go ahead and figure out how to fix it before moving on.
Display stats in a table
Now you are going to add a table to your app to display information about the number of points, order of fit, St, Sr, and r2 value.
- In the Design View, drag a Table in.
- There will be five columns named NumPts, Order, St, Sr, r2 -- make these changes in the Names dropdown in the Columns section of the Configuration block in the UITABLE PROPERTIES menu (whew!).
- Make the table wide enough to see all five columns.
- Go to the CodeView. Think about where it would make the most sense to update the table values. CalcStats is where the information will be calculated, so this is probably the right function to also update the table.
- In the CalcStats function, add a line that will load the appropriate information into app.UITable.Data:
function results = CalcStats(app)
Dbar = mean(app.Disp);
Dhat = polyval(app.Coefs, app.Force);
St = sum((app.Disp-Dbar).^2);
Sr = sum((app.Disp-Dhat).^2);
r2 = (St-Sr) / St;
app.UITable.Data = [length(app.Force), app.OrderSpinner.Value, St, Sr, r2];
end
- The table is clearly too tall - in the Design View, you can shrink the table to make the size make sense for the number of rows (1) you have.