[MUSIC] Okay, welcome to the second part of our introduction to App Design. In the previous lecture, we introduced you to the fundamentals of GUIs via a working example, which I've copied here do I can reopen it in the App Designer by clicking on its file, which has the standard extension mlapp. I use the term working example loosely, because to tell the truth is app is not working so great. Let's try it. We've added all the widgets we need, but only two of them do anything. A set of axes in which plots of temperature and average temperatures appear, and a set of radio buttons that determine which of these plots will appear. The rest of these things look great here on the front, but they are hooked up in the back. In this lecture, we're going to finish the job. To hook up our widgets into the code that's behind all this functionality, we need to give each one of them a callback function. Let's get some callbacks first the start knob, which will set the year of the start of the plot. Right click, go to Callbacks. And there are two functions that we can add. One name has the words value changed in it. And the other has value changing. What's the difference? Well, the difference is that as we turn the knob with the mouse, the value changing function gets called repeatedly. But the value changed function gets called only once when we release the click of the knob. Since plotting a few hundred data points can be done very quickly, we can afford to have our callback function called many times without any lag. In general, if what we need to do in response the widget event is too time consuming, we should use the value changed callback. But in our case, we'll go with value changing. Then here's our callback. As with the button group, the function has the two arguments, app and event. And there's an assignment statement that the designer of the App Designer thought we might like to use. It assigns the value property of the event to a local variable name changing value. Well, we'll change this in a bit but first I want to add callbacks for the other widgets. So let's go back to the Design View and do the stop knob. There is its callback with the same setup. And let's go back to the Design View again and do the same thing with the slider. Again, it looks the same as the callback for the knobs. And last but not least, the Default Settings button. No choice this time. This time there is no assignment to a local value. That's because there's really nothing different from one button press to another it's just the fact that the button is pressed that counts. Okay, now let's run it and see what happens when we move these newly activated widgets. Nothing happens. Nothing happens because we aren't doing anything and the callbacks. A do nothing callback doesn't help, but it doesn't hurt either. Okay, time to make these callbacks do something. Back to Code View. Let's start with the start knob. A very good place to start. And what should this callback do? We want to track what start year the user selects and update the plot accordingly. So we need the year value from the knob and that happens to be stored in the value property of the event object. So let's add a property to store the start year. And while we're at it, we might as well go ahead and add one for the stop here too. Now let's change the to knob callback so that they update these new properties and called plot data to do a new plot. Now we need to make the plot data function use the start and stop your properties to limit the plot. Well, where is it? I can scroll up and down looking for it and that's not too bad with a small app like this, but there is a better way. Look over here at the left. The code browser has three tabs, callbacks, functions and properties. Plot data doesn't show up in the callbacks because it's just plain old function. But if we click functions, and there it is, and if we click it, the scrolling is done for us. So how should we set up the stop start limits. One option is to use the colon operator to restrict the x and y values to the plot function. But we call it twice, so we would have to set the correct indices in four places. Here's an actually much slicker solution, we add two lines like this. The first line forces the axes to the range we give it and the line that says manual freezes the range even when we use the hold command and plot something new. So are we ready to run it? Well, no, because we need to initialize, start here and stop here in the startup function. Let's do that. Okay, let's test our app. I was trying to start knob, nice. How about the stop knob? And this thing is working. And the plotting is definitely fast enough to keep up with us turning the knob. It's nice and responsive. What's happening? Okay, look at our knobs. The start knob is farther to the right than the stop knob. So we're setting the beginning year to be at after the ending year, and that not only violates the meanings of start and stop when we're talking about time limits, it also violates a MATLAB rule that the first limit for a plot axis has to be less than the second limit. So how do we fix this? We need to keep the start value from becoming greater than or equal to the stop value property. We could just freeze the plot when that rule is violated, but instead of that we're going to do something much better. Do you remember when I showed you the completed app and when you tried to move one knob past the other, the second knob moved, and I said this is an example of something we would be writing code to do? Well it's time to write code to do it. I'm going to pop in some code that moves the second knob enough to keep one year between them. One, two, three, pop. And there it is. The if condition checks to see whether we're within one year of the stop year or even potentially already past it, if so, we set the stop year to be one year past the start year. We use this min function here to make sure that we don't go past the stop knobs upper limit, which is number 2, the lower and upper limits and happens to be 2020. And we update the stop knob itself by setting to stopknob dot value to the stop year. Finally, we make sure that the startyear is one less than the stopyear, and we update the startknob dot value. And while you weren't looking, I popped in the code for the stop knob too. Is the same thing or the opposite, if you look at the details, where the start knob has a greater than and a minus one, the stop knob has a less than and a plus one, where there's min, there's a max, and so on. But it's basically the same idea. I'll let you check it out on your own. I know you want to see this in action and here we go. Is that pretty cool or what? All right, perfect code on the very first try, no bugs. Perfect. Well full disclosure by first try. I mean, first try on camera. There might have been maybe a few tries before that, full disclosure by a few, I mean no more than let's see, 12, 13, maybe. So things are moving around on the screen the way we want them to. But there's something that you might not have thought about, that's going on behind the scenes. These knobs are moving all right, but where are the plot commands that are making them move? How are the pixels getting updated on the screen? Well the simplest explanation is the MATLABs doing it. If we change the knob value, MATLAB notices the change and quickly updates the visual appearance to reflect the change. That's a great thing too, because if MATLAB didn't do it automatically, then either we'd have to write a lot of very complicated graphics commands to make it happen or the GUI would get out of whack. So we could just stop with the explanation that MATLAB notices the change and updates the pixels. But that's sort of like saying it happens, because it happens. How does it happen? How does changing the stopknob value trigger the change in the display? Well some code does it of course. I mean, code is making everything you see happen, and where have I heard that before, a movie or matrix maybe? You know it's getting more true every day too, in fact for all you know, I'm a robot. I just checked that I'm not a robot box to fool everybody. But where is the code that does the graphics? Well you can see it's not in our app. No, it's not there. It's in the class definitions of the widgets. Do you remember when we were talking about the constructor for our app. And we saw that the constructor called create components down here, create components, creates an object for every widget which it calls a component. It does it by calling a built in function for that widget. Let's see. Yeah, here we go. Right here, it's calling the function you are knob, which means user interface knob. And returns a knob object. Edit assigns the object to the property name start knob. The code that manipulates the picture of the knob on the canvas is inside a method of that object. The class definitions for our knob object and for all our other widgets are kept deep inside the make, I mean inside MATLAB. And those definitions include set access methods that handle the graphics changes. Do you remember the set access methods? We talked about them near the beginning of that riveting first lecture that I gave you on object oriented programming. Who can forget that? Well if you don't remember it, you can replay that part. And if you do happen to remember it, and maybe you also remember that whenever a value is assigned to a property, the set access method for that property gets called automatically. And that's what happened when we assigned a new number to the value property of the start knob. The set access value for the value property was triggered inside the startknob object, and it changed the pixels on the screen to make it look like the knob moved. So that's why knobs appear to rotate, the sliders appear to slide, the radio button dots move from one button to another, and the bullets glide by Neo. Well, now let's turn from the knob and slide to the slider. We need to make it call back work. The next steps are pretty routine now. We add a new property, And add new code to the callback to set the new property. So just three lines in this method. Assign the slider value to the property, recompute the averages, and plot. That was easy. So let's give it a try. Wait a minute, we're forgetting something. Let me scroll up and you'll remember it. There it is. We put that comment in there for just this moment, we finally introduced the window adjustment. So we better use it to compute the moving averages instead of just using 30 every time. And here we go. Okay, I'm feeling lucky. Let's run it. No, I keep making the same dead blasted mistake over and over. I forgot to initialize the property value. The routine should be one, add a new property, two, assign it a value in the callback, and three initialize it. Maybe it ought to be two, initialize it, and three, assign it a value. But anyway, you need to do all three of those things. Of course, I can forgive myself for making mistakes, because I'm contending with all this equipment and electronics and harsh lighting in this studio, not to mention my hairstylist and the makeup people who don't seem to care whether I'm on camera or not. And all those other people running around doing whatever it is they do to produce these videos, I still haven't figured out what the best boy and key grip are doing over there next to hard cash, it's probably a union thing. But at least I know how to do what I need to do, if I can just remember to do it with all these distractions. So here goes, I'm just going to use magic again, initial window, wow, cool, I need to remember that spell, let's try running it again. If we go all the way down to six months, the red average line is very jagged, but that's what we expect. Moving it up to the other end, to 120, it's nice and smooth, so this lighter is working. What's left? Yeah, we got one final call back to put code in, the one for the default settings button here. Well, you can't get much simpler than that, the only complication is that there's no set defaults function. Let's make one And let's fix the heading. Okay, so we need to add code to put the app in its default state, so what do we want the default state to be? Well, we want it to be the same as the initial state, what do we want the initial state to be? You can weigh in on that later, but since I'm already on a roll, here's what I think it should be. The first command, sets the slider at half of its maximum value, these three commands cause the both radio button to be pressed. And these two commands, set the start knob to its minimum, and the stop knob to its maximum. And we need to set all the properties that depend on these widget values, Proper Terra, how the heck with it, there. And finally, to display the default plot, we need to compute the averages plot the data And that's our set defaults function, and guess what? Now that we have this function, we can simplify our startup function a lot. It's so simple now that I've taken out the comments, we don't need them Okay, let's trot this beauty out, and put it through its paces. He's either a big fella,we're just going to take a few laps, and see what you can do. Now that's beautiful. We done? Well yeah, for all the major things, but there's still a few tweaks I'd like to make let's start with the easiest ones. One thing that keeps bothering me, is the way the scale of the y axis changes, when we change the start, or stop knobs. Maybe it's just me, but I think that makes it hard to see what's happening with the plot, let's turn that off. We need to pick a range for the y axis, and stick with it. Let's fix the range at the values that MATLAB, chose at the beginning to cover the entire range of temperatures, which are minus 1.5, and plus 1.5. Again, we freeze them with the manual setting, and let's add some grid lines, okay, let's see what those baby steps did. Now that looks better, and the grid is light enough not to be distracting, but just dark enough, so you can estimate the X,Y values for an intersecting point. And if you're interested in a particular point, or a particular region of the plot, look up here at the top right of the plot. We've got the same little standard icons we've seen before, they'll let you do things, like save a copy of the plot, zoom, shrank, pan, just like for normal plot axes. Let's zoom, and pan a little bit, and after those easy ones, let's make a change it's a bit harder. As I was telling you near the beginning of this lecture, the moving average function slides a window across the data, and computes the average of the data points of fall within the window. We've been using the default setting of movmean, which takes the same number of data points to the left, and right to the current point. In other words, the window is centered around the current data point, not certainly where we want. What happens at the very beginning, and very end of our data vector? At the beginning, there is no data to the left, so movmean, uses only data from the right. So it averages about half of the usual number of points to get the result, and as we start sliding to the right. It'll include more, and more data points to the left, as they become available. So the average is biased in these cases toward temperatures at later times, instead of being weighted equally. And the opposite thing happens, at the other end of the scale. This is a small flaw, because it affects a small fraction of the total number of points, but let's fix it. We'll eliminate the flaw, by simply not plotting averages for those points in the plot data function. The number of points that we cut out, depends on the width of the window, and how close to the center of it is in the range. Here's code that will do it. To understand why we compute the start, and stop values this way, let's read the first few sentences of the explanation of the moving average. Movmean, moving mean value, y equals movmean of XK, for a vector X, and positive integer scalar K, computes a centered moving average by sliding a window of length K along X. Each element of Y, is the local mean of the corresponding values of X, inside the window. With Y the same size as X, when K is even, the window is centered about the current, and previous elements of X. The sliding window is truncated at the end points, where there are fewer than K, elements from X, to fill the window. If you read this carefully, you'll realize that when K is even, movmean calculates the average using one more point from the left, and from the right. That's why we take the floor, and head one for the start calculation, and conversely, use the ceiling, and minus 1 for the end. Check the numbers by hand with a window size of six, which is the minimum value we use here, and then was seven. And you'll see that indeed, we're plotting exactly those points that were averaged was six, and seven. And since all this really has nothing to do with gooeys, I won't spend any more time on it. And if I spend too much time on it, you might realize that there's still a tiny flaw, for Windows is widths, or even numbers. Is pretty trivial, and we'll fix it by forcing the window size to be odd inside the averaging window. And by we, I mean you. Let's see whether it works. Watch the red line as I change the window size with the slider. You see it slide away from the edges of the plot when I increased window size. Let me turn off the monthly plot clicking monthly average. Now watch, like I said at the beginning of this video, it looks like a snake. It's got a very bright red color. And from what I've heard, bright colored snakes are likely to be deadly. And speaking of deadly, in the beginning of this lecture I reminded you about the plot we did for that live script in lesson three. We showed a plot like this red snake, in which we also used move mean to smooth out CO2 fluctuations. That helped us see that the Earth's CO2 level is curving upward exponentially. Here in lesson six, move mean helped us see that the Earth's temperature is also rising and it's curving upward too. What do you think, is there a correlation? Most climate scientists say yes. They also say the carbon dioxide increasing is causing the temperature to increase. Well, we're not doing climate science. We're doing MATLAB. And during this lecture and the previous one, we built our very first MATLAB app with a pretty nice GUI. And as we built it, we learned a lot about GUIs and how they work, and how MATLAB implements them with the App Designer. We learned that the App Designer uses object oriented programming, and helps us put the necessary properties and functions into a single class definition for the entire app. We learned that some of the methods in that class definition are termed callback functions, which are functions that are called automatically when the user does something with a mouse inside a widget. We learned that widgets are active regions inside the app, each of which has its own picture, typically with moving parts. And each of which is connected to its own callback function. We used a variety of widgets to build our app, including buttons to push, knobs to turn, a slider to slide, and a set of axes to plot in. And finally, we learned how to add nice looking colors. Of course, our tour of the App Designer has not covered everything but we have presented the basics. And that should be enough for you to explore the rest on your own. The best way to do that is incrementally. When you need to build an app and you need a new kind of widget that you've not used before, just start playing with it. Taking baby steps as you add code, and setting breakpoints when bugs pop up, and they certainly will. If you run into something that you just can't solve, Google it. The chances are good that someone will have posted the solution online already. Probably on the Math Works site, MATLAB Central. Okay, now you know how to create an app. But we're not stopping there. As we promised, we're going to show you how to make that app a lot more valuable. We're going to learn how to turn it into a standalone application, which means that it can be run outside of MATLAB. And by that I mean you can convert it into a program that can be run on computers that don't have MATLAB installed. Without using MATLAB online, that aren't even hooked up to the Internet. That's what converting to standalone means. And it's really amazing just how easy it is to do once you know how. So get ready for our lecture on standalone applications and get ready to be amazed. [MUSIC]