Difference between revisions of "User:DukeEgr93/CBApp"

From PrattWiki
Jump to navigation Jump to search
Line 1: Line 1:
 
Steps:
 
Steps:
* Select a set and load data
+
== Select a set and load data ==
** Add a button and have it simply load Beam01.dat
+
* Add a button and have it simply load Beam01.dat
*** Drag button onto app
+
:* Drag button onto app
*** Change text to Run
+
:* 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:
+
:* 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>
+
::<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
+
:* 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:
+
:* Add code in this to load the data, split it, and put it into appropriate variables:
:::<source lang=MATLAB>
+
::<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:
+
:* 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>
+
::<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>
+
::Results:<source lang=MATLAB>
 
K>> Data
 
K>> Data
  
Line 69: Line 69:
 
K>> dbquit
 
K>> dbquit
 
</source>
 
</source>
* Plot the data
+
== Plot the data ==
:* Go into Design View and add a set of axes
+
* Go into Design View and add a set of axes
::* Change the axis labels and titles as needed
+
:* 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
+
* Go into the Code View and add code to the RunButtonPushed function to plot the data and add a grid
::<source lang=MATLAB>
+
:<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>
* Next we will hard-code a first-order fit; later, we will make the code flexible for higher order fits.
+
== Calculate and plot fit ==
:* In Design View, add a spinner and call it Order
+
Next we will hard-code a first-order fit; later, we will make the code flexible for higher order fits.
::* 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.
+
* In Design View, add a spinner and call it Order
:* 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.
+
:* 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.
:* In the Code View, make a new public function called CalcFit
+
* 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.
::<source lang=MATLAB>
+
* 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.
+
* 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>
+
:<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:
+
* 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>
+
:<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:
+
* Add a changed callback to the OrderSpinner to update the plot when the spinner value changes:
::<source lang=MATLAB>
+
:<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:
+
* Add code to the UpdatePlot function to get the new coefficients and use them to plot a model:
::<source lang=MATLAB>
+
:<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:

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.