Welcome to lesson 6, the final lesson of this course. This title says Applications, which could mean simply examples of ways that MATLAB can be used. But we actually mean something much more specific than that. We've already created lots of functions in both this course and the first one, subscripts, and in previous lessons, even some classes, all of which serve as examples of ways that MATLAB can be used. But if you want to try to run any of them, you've got to do it inside MATLAB. If we wanted to give one of these marvelous programs that we've created to our friend to try it out, she'd have to have MATLAB installed on her computer or a license to MATLAB Online. What if we wanted to share our work with people who don't have access to MATLAB? Or if we wanted to sell our MATLAB program online? Wouldn't it be wonderful if we could create a standalone application that anybody can run on any computer, whether it has MATLAB on it or not? Well, by now, it should be obvious to you what I'm going to say next, you can. You can use MATLAB to make standalone apps. In this lesson, we're going to show you how. But first things first, nowadays pretty much all applications use something called a graphical user interface or GUI for short, spelled with initials G-U-I. What is a graphical user interface? If you didn't take our first course, you may not recognize the name, but you know what it is. You're using one right now to watch this video. In fact, I'd bet that for most of you young people out there, and by young I mean way younger than Akos, the correct question would be, what is a non-graphical user interface? For a long time after the dawn of the computer age, there weren't any GUIs at all. The word graphical in graphical user interface means picture-based. Where a picture includes not only sunsets and faces, but also icons and buttons that you can click and stuff like that. But a computer in those days couldn't show pictures, and there was no mouse for clicking icons and buttons anyway. The interface between the user and the computer was totally non-graphical. It was all texts being typed on a keyboard and text showing up on a screen. Do you remember PCs before Windows? I'm guessing that most of you probably don't. Well, this is what a typical PC screen looked like in the 1980s. Back then, most PCs ran MS-DOS, which stands for Microsoft Disk Operating System. This is a system that Bill Gates bought for $75,000 in 1981 and then turned it into a huge moneymaker. It was state of the art back then, but it was all text in and text out. Working with it looked like what you see behind me. Well, actually I'm cheating a bit here. This isn't an old PC screen. It isn't even MS-DOS. It's an application that comes with windows called Command Prompt, which most people never even use. You can see why. It looks a lot like an MS-DOS screen from long ago and it works like MS-DOS. In any case, this is an example of a non-graphical user interface, and most people call it a text-based user interface. When computers finally advanced to the point that they could display graphics, and when the mouse was finally invented, the graphical user interface or GUI, took over the world. What is a GUI again? A GUI is an interface that allows a user to interact with the computer application through various graphical objects, such as icons, buttons, menus, toolbars, windows, status bars, pictures, and other widgets. These GUIs have become quite sophisticated, and I'd like to draw your attention to a great one. Let's see, where did I put that great GUI? It was right here. Surprise, it's the MATLAB desktop. I fooled you, didn't I? Not even a little bit? I guess it is obvious because the MATLAB desktop has so many clues that it's a GUI. Here's an icon. Here's another one. Here's a toolbar. Here's a menu, and of course it has many windows; the Current Folder window, the Workspace window, the Command window. Let's look at that Command window for example. It's actually a text-based interface within a window. But it would be pretty limiting if this text-based interface were the only way to interact with MATLAB. I for one wouldn't even use it if that were the only option, much less teach a course on it. MATLAB's graphical user interface is one of the great things about it. Why are we talking about GUIs when this lesson is supposed to be about applications? Well, most regular applications that you work with every day have GUIs, so most of the MATLAB programs that you want to share with others should too, they're going to expect it. If you want to create a standalone application for your MATLAB program, it should have a GUI. Being able to create a GUI is an important skill. In fact, it's so important that MATLAB comes with a handy tool to help you do just that. It's called the App Designer, and we're going to learn how to use it. It's called App Designer because applications based on GUIs are generally called apps. As usual, I'm going to show you how to do something through an example, so we're going to use the App Designer to build an app. We'll do all that in two lectures, this one, GUIs part 1, and the next one, GUIs part 2, and then in the lecture that follows these two, we'll learn how to transform the app into a standalone program that you can run without even having MATLAB installed. Unfortunately, that transformation cannot yet be done in MATLAB Online, so I'll use an installed version. For consistency, I'm going to use that installed version which is released 2020a throughout both this lecture and the next. For this lesson, we're once again going to write a program that demonstrates a global change. Remember how we taught you in lesson 3, how to create a live script by making one that illustrated the history of the change in carbon dioxide levels in the Earth's atmosphere measured at amount lower, well, we're going to teach you how to create an app by making one that illustrates the history of the change in the Earth's surface temperature. Berkeley Earth is one of the leading research institutes when it comes to climate science and we're going to use data that they published on their website. It's located at berkeleyearth.org. Let's go have a look at it. Let's click on "Data" and select the "Land + Ocean Data" set link, and then click on "Data Overview" in the top menu to get to this page. Scroll down to Land + Ocean (1850 - recent) and click monthly global average temperature (annual summary), it'll take you to this page. As you can see, it describes in detail what the data is and how they got it. For our purposes, it suffices to say that this is an estimate of the average global surface temperatures from 1850 until 2020, it's a relative measure to illustrate trends. The temperature in the period between 1950 and 1980 was pretty stable, so it took the mean temperature in those three decades and set that to the baseline or zero. All the data points in the data set are relative to that, they call this measure temperature anomaly. You can see the first column is the year, the second is the month, and the third is the estimated global average temperature anomaly. We only use these three columns for our app. Note the fourth column, which is uncertainty. Obviously estimating temperatures for the 1800 is not going to be as accurate as it is today. As you can see in 1850, it was 0.372 Celsius, but as we scroll down, it goes down to 0.05 by 2019. Since we're more interested in what's going on now, our simple app will not use the uncertainty measure. To get this data into a form that we could more easily use in our app, we extracted the first three columns, combined the year and month values into a single fractional year to make it easier to work with, converted it into a MATLAB array and saved it into a MAT file. Let's get back to MATLAB and load the file which we named GlobalTemp.mat. It's a two-column matrix with 2,040 rows, which happens to be the number of months from January 1850 to December 2019. Let's see the first 12 lines of this array. We converted the year and month values into a single number to make it easy to work with the data. For example, we can plot it. Now that we understand our data, let's look at the app that'll make this data come alive, I've got it in this folder right here. One of these files is the app, it's the one with the extension that means MATLAB app. Let's right-click it and select Run, and voila! That's quite professional looking when you say, "This is the app that we're going to create from scratch." As you can see most of the real estate is taken up by a figure window with two plots; one in blue and one in red. Real estate, by the way, is what cool people call portions of the computer screen. If you want to be as cool as me, well, if that's even possible, you should call it real estate too. The blue line is what you saw before; a plot of the monthly data from Berkeley Earth. The red line is a moving average of that data. We use the same idea that we used in that live script in lesson 3 when we smoothed the CO_2 data. At every month, we take the value of the temperature at that month and the values before and after and compute their average. Once again, you can visualize it as a window of fixed width moving across the data while we take the average of what's in the window. The overall result is a plot of monthly temperature in blue and monthly average temperature in red. Now, what about these widgets below the plot? Well, I should first stop and comment on the word widget. It's a general term in English that means vaguely, something that does something. But when it comes to GUIs, it has a very specific meaning, which is something that does something. It's a picture in a region of a GUI that causes something to happen when you click and/or move the mouse inside it. Maybe it causes something to be plotted, or text to appear, or a slider to move, that sort of thing. Examples are the best way to explain widgets, really the only way. Let's go from left to right. The little circles below the words data source are called radio buttons. You can select only one option at a time in this widget and that's where the word radio comes in, because many radios have buttons to select discrete tuning frequencies that work like that. Right now the button labeled "Both" is selected. I'm going to change it to monthly by clicking the top button, and the red line disappeared. Now, let's try monthly average. Now, we see only the red line. I like to see both, so I'll go back to that. This Start knob here is a widget that changes the year which we start the plot. You can see how the plot shifts and stretches as we turn it. We've got a Stop knob, it changes the upper range of what we plot. Notice that if we try to move the stop year to be before the start year, the start knob moves to keep that from happening. As you'll see, this behavior is one of the many things that we have to write MATLAB code to do. Here on the right-hand side, we have a slider widget, which is labeled averaging window. This slider sets the window size for the moving average. As you can see, the default is 60, which means that to get a value on the red line for a given month, we calculate a 60-month average of the blue values centered on that given month. Let's see what happens if we change that. As we move down towards the minimum of six, you can see how the red line gets more and more jagged, which is of course, what you'd expect when you average over fewer months. Now, let's use our knobs to zoom to the period 1945-1974. That's a pretty special period of time, well for me anyway. I was born in 1945 and I got my first teaching job in 1974. It was a pretty exciting time for me, but not so exciting for the temperature of the Earth's surface. Overall, it hardly changed at all. Let's raise the window size to 120 months. See how nice and almost horizontal this plot is. Now, let's see what's happened since then. Well, it's only a three-quarter degree increase, but it's a very steady increase. But why does the red line stop at 2015 instead of going all the way to 2020? Remember the current window setting, 120 months, that's 10 years, which means that, we need five years worth of data before and five years after the current measurement. So 2015 is the latest date for which we have enough data to compute a 10-year moving average. See what happens as I slide the slider back to six. In addition to the smoothness disappearing, the end of the red line shifts closer and closer to 2020. Looks like a snake. What about this button here called Default Settings? It restores everything to the initial state, so now the app looks like it did when we started it. This is our little app. Would you like to learn how to build it? Thought so. Or high, let's do it. I'm going to close our app by clicking the little "Red thing" and go back up to our original folder for this lecture. I've got another copy of the data file GlobalTemp.mat here. All we need to do is design an app to use it. We can open the app designer in a couple of different ways. Select the "Home" tab then pull down the "New button" and pick the option named App. Or in the Apps tab, click the first button, "Design App". Either way, a new window pops up that gives you a lot of different options. For the sake of simplicity, we'll just select "Blank App". A new tab opens up in our browser, if we're using MATLAB Online, but a separate window pops up if you're using an installed version, as we are here. Otherwise, the differences are trivial. On the left of the window you see an array of icons. Each one of these represents a widget, including the ones that we just used. The section in the middle is called the canvas. The canvas is the area in which you design the GUI layout, like a painter painting with oils on a canvas. Over here on the right, we'll see list show up with the components that we put into our GUI, and you can see up here at the top at this section is in fact called the component browser. Right now it lists only app.UIFigure. UI shows up a lot with apps. It means user interface. If we select app.UIFigure by clicking on it, all of a sudden we see a bunch of different options pop up below it that we can play with. We'll leave these alone for now. By the way, this app.UIFigure syntax might give you a hint of something to come. UIFigure is a property of an object named app, and we're going to be using our new found object-oriented programming skills shortly. Let's go ahead and add the plotting area of our app. In MATLAB, it's called axes, or they're called axes. So let's drag it or drag them in and resize it or them, to fit the top area of the window. In the component browser here you can see that we have a new component called app.UIAxes, and it has even more settings that we can change. Let's set the title and axes labels right now. Let's make the title Global Temperature Anomaly, and the X label can be simply year. How about this for the Y label? C, and in parentheses, relative to the 1950-1980 mean. Let's save our app by clicking here. Let's call it global temps, keeping the suggested extension MLAB for MATLAB app. Now let's run it to see what happens. Again, we just click ''Run'' right up here. It pops up in a new window with the axes, tittles, and the labels we specified. Of course, it doesn't do anything yet, but we're on our way. Let's close it and go back to the app designer. Before adding the other widgets, why don't we add the code that reads in the data and plots it at the beginning when the app starts? How can we do that? Let's select app.UIFigure in the component browser. Right now, we're looking at this tab called Inspector, but we want the one next to it called Callbacks. Let's click that. See this list of items grouped into categories called common, keyboard, and window? They all have this box with function and a dot, dot, dot next to them. If I click in one of them, I see that it's really function name. So what in the world are these things? These are places for names of so-called callback functions. What is a callback function? Well, it's a function that gets called when a certain event occurs in our app. That's the code triggering I was talking about when you do something while the mouse is inside a widget, it's actually function triggering. The trigger can be clicking a mouse button or hitting a key on the keyboard, and starting and stopping the app can trigger a call back too. When your app is running, its callback functions are on-call waiting for their individual triggering events and you will never have to write a function called call or a callback function. That happens automatically, which is something else that cool people say. Also really cool people usually just say callback instead of callback function. Let's look at a callback. We'll start with one named StartupFcn. Well, we rocket scientists can easily decode this name. It means Startup function, and it gets called just after the application starts. Well, this is the perfect place to load the data. Let's click the down arrow and select the default name it offers, StartupFcn. This is the name of the startup function as it will appear in the code. Whoa, did you see that? Look at all this code that just popped up. All I did was click on the name. By the way, if the code doesn't pop up for you then just look up here for the Code View button. It'll be grayed out and looking like it's dead, but it's not. I think it ought to be brighter, but just click it and the code will pop up. Well, let's see what we got here. The first line tells a lot right away. This is a class definition for a class named GlobalTemps. Hey, that sounds familiar. GlobalTemps. Yeah, that's the name we picked when we saved our application into a file, three or four minutes ago. Folks, with this class definition, we had just waited hip deep into object oriented programming. Man, it's a lucky thing that our object oriented programming lectures happen to come before this one. Just another lucky coincidence, I guess. I have to ask [inaudible] if he has any idea how that happened. But where did all this code come from? Well, this code is an example of some of the automatically generated code I was talking about a little earlier. It makes things easier for us app designers, and it's generated by app designer. Wait, I'm the designer here, the program is just getting me things I need for my design. Let's see what would be a better name. Yeah, App Designer Gopher. Well, while I put that excellent idea in the suggestion box, why don't you take a look at this Design View button up here. Can you guess what that button does? Yeah, it's just the Canvas. I wonder why they don't call it Canvas View. Okay, another one for the suggestion box. Anyway, I'll click on "Code View" and we're back looking at MATLAB code again. Now, I'm going to be daring and type some code. I'll type my name right here under the class def keyword. Well, that was a flop, nothing showed up. Well, let me type anything. Well, it won't let me type in the gray areas anyway, but what about this white area in the function, StartupFcn. It's a different story and you can probably guess how this works. The gray areas are generated automatically when you add or change features in the Design View. It's just better all around if you can't change the automatically generated code accidentally or on purpose. Whereas you'll need to make changes in some areas and these areas have a white background. The editor enforces these rules. It's obviously not the normal editor that we're used to for normal functions and scripts. It's an app design editor enhanced for app design just like the Live Script Editor is enhanced for Live Script design. The enhancements are nice of course, but I can't say that I like having to learn three editors. If I had my way, there would be just one editor that had every feature we needed. Let me jot that down. We may need a bigger suggestion box. The app designer keeps the graphical layout and attributes that we modify in the design view in sync with the corresponding MATLAB code. For example, you can see that the designer wrote the title that we chose for our plot into this title command, Global Temperature Anomaly, so we don't have to worry about this detail or hundreds of others that it takes care of. We can focus on the layout of our GUI in the design view and focus on special functionality in the white areas of the code view. Before we add any more code to the Startup function. Let's look around a little. First, note that our GUI class is actually a subclass of a class called matlab.apps.AppBase. This is a built-in class and implements many of the details related to the operation of a GUI based app. In addition to whatever properties might be inherited from the base class, GlobalTemps has two public properties: UIFigure, which holds the figure object that serves as the main app window, and UIAxes, which holds the set of axes that we just added to that figure. Look at the create components method here. This is a private method that creates the main figure and stores it in UI figure, and creates the set of axes and stores it in UI axes. This method not only sets the title of the axes, but also the x and y axis labels. It sets the position of the axes within the main app window according to the moving and stretching of the axes that we did with the mouse. After it's done with all that, it'll set the work creating an object for each one of the widgets that we dragged into the Canvas. It does that by calling functions that create objects and return them as output arguments. It sets the parameters we chose for them, like titles and labels and positions and so on. If the app designer didn't automatically generate all this code, we can still write it of course. But instead of spending a couple of seconds with a mouse to automatically generate it, we'd have to laboriously type in every character as we do in normal functions, methods, properties, and class definitions, and then debug all of it. That would be painful. Modifications would be painful too. But with the app designer, you can make changes in the design view and MATLAB takes care of the rest. My gosh, I sound like a TV commercial where really believe me, I've tried it and it works. Only smokes that sounds like one of those awkward late night endorsements by some has been celebrity. Hell, I assure you that I'm no has been celebrity. No. I consider myself to me more than never was department, and that department doesn't get endorsement deals. Tell you what, let's look at something else. If we scroll down to this third method section, here's the class constructor. When the app starts, it creates an object of the class global temps. As you know, when an object is created, its constructor is called immediately. This constructor uses the local name app for the object it creates and the comments tell us what it does with the app. First, it creates a figure and components for it. Second, it registers the app with the app designer, which is some internal MATLAB, a housekeeping and we don't need to worry about. Third, it executes the startup function. It does that indirectly by calling a built-in function named runStartupFcn with two arguments, app and a function handle for startupFcn. So hey, that code I put in startupFcn has no semicolon. So if we run this app, this constructor will get called, it'll call runStartupFcn, and that will run startupFcn and well, let's try it. There you go. There's our cool guy, right there in the command window. Now, we know how this function actually gets called. Thanks to cool guy, we know that it actually does get called. That's useful information. But maybe we can put some code in there and that might be a lot more useful. So what do we want to do instead of printing the name of a cool guy? Well, for one thing, we need to load the data from the Global temp.mat file and plot it. So let's try that. We can use a load command to get the data into the workspace. What's this little squiggly red line under the load command? Let's see what it says. It's warning us that this load command might pull in a variable with the same name as some function that we will want to call. As a result, we won't be able to call it. Well, to remind you, as we said, this mat file just loads in one variable named data. I know we're not going to call a function named data, but I don't like that ugly squiggle. So I'm going to get rid of it. To get rid of it, you just add a list of the variables that are loaded in. In our case, it's just data. One ugly little squiggle gone. Yeah, I see the 100 data, but that'll be gone too as soon as we use data in a command. Also to remind you what's in that data variable, it has some time points at which the temperatures were measured in its first column and the temperatures themselves in its second column. So let's plot the data with the first column on the x-axis and the second column on the y-axis. You can see here that we're including an argument to plot that comes before the x and the y data. It specifies the axes that it's plotting into. In this case, it's a property variable named UI axes, which we talked about a little earlier and which contains a handle for the axes that we dragged onto our Canvas in the Design View. Let's run it. Here it is, so easy. This thing is already looking pretty good. Before declaring victory though, let's step back and look at the code a little bit more carefully. We loaded globaltemp.mat. Matlab created the variable data to hold the time points and temperatures and it created it in the scope of the load command, which is inside the function StartupFcn. That works for plotting in StartupFcn, but unfortunately, the moment StartupFcn exits, the variable data exits with it because it's a local variable. When the user is using this app, he or she will need to plot the data over and over. So clearly, we don't want to throw the data away and then reload the data every time we want to plot it. We should store it somewhere in the object, somewhere that's more permanent than the local scope of a method. Do you remember where we store data in an object? Right, in its properties. We should create a property or two in the class definition to hold the data and write a couple lines of code in the StartupFcn function to copy the data into them. But how can we add our properties? Well, we sure can't type it in the way we would with a normal class because the property section is all grayed out. Have a look around the app designer windows. Anything promising, like around here? That's it. This big red button labeled property. Well, that is irresistible as the Drink Me signs in Alice in Wonderland. Let's click it. Suddenly, we're in. It's given us a new property section, which it has made private. This new section is white, which means that it's editable. So we can change private to public if we want to. But since we have no plans to give access to our properties outside the application, it should stay private. In fact, that holds in general. If there's no obvious reason for divulging a property to the outside worlds, it's best to keep it private. Here we go. We'll put in two properties, temperatures and time points, and provide comments about them. Now let's go back and modify the startup function to store the data in these properties and use them in the plot since their names are more meaningful than the all-purpose name, data. Let's run it again just to see that we didn't make any mistakes. Baby steps, you know. Works the same as before. But now we've stored the temperatures and time points in the properties for use by any methods that need them. Now that we know how to add code to our app, let's go back and add more widgets. We click "Design View", the Canvas shows back up. Let's drag this radio button group widget into the left-hand corner. We can double click on its title and type in Data Source. Similarly, we can change the names of the individual buttons one-by-one, monthly, monthly average, and both. If we needed another button, we could simply right-click and select the "Add Button" from the context menu, but three is all we need now. Let's show both as being the button that's been pressed when the app starts. To do that, we click on "Both", and then over here in the inspector, we click the checkbox for value, which tells the app designer that the both button is the starting value for the radio button group. Now come to the start and stop knobs. Let's scroll down the component library, find the knob widget, and drag it in. For my taste, the label which is currently knob, is too far below the knob, but we can grab it and position it wherever we want. Let's change the name to start. Let's see. These numbers aren't what we need. They go from 0-100. We want the limits to match the years in the data, which go from 1850-2020. How can we change them? Click on the knob to highlight it and look at the inspector window over here on the right. We want to change the limits, which we do by typing in 1850, 2020. There. Now we want the initial value to be 1850. Well, that's what Matlab picked. It's reading my mind. What about the tick marks? I don't much like these default values, they're too many of them, and they're not nice round numbers. Let's just have four. We double-click in the major ticks window to select them all, and type 1850, 1910, 1960, and 2020. The labels update automatically in the knob. By the way, you can separate the numbers with commas, semi-colons, or spaces because these are just entries into a Matlab vector, and either row or column vectors work fine. You can even use the colon operator. Now comes the stop knob. Let's save some work and copy paste the Start button. Command C, Command V, on a Mac, or Control C, Control V, if you're running an installed version of Matlab in a Microsoft Windows environment. Now let's just drag it and align it with the other knob, there. Let's set the default value with the inspector to 2020. Now all we need to do is change the label to stop. That turned out to be easy. What else? Our slider for the number of months to average. Let's scroll our component library up. There it is on the left. I'll drag it over here. That looks good. I'll move the label up to the top. Good. Let's change the text and the label to averaging window. Now let's arrange everything so it looks good. Now we need to change the limits. But we're already experts on that. We'll set them to six and 120 months. The value should be set to 60 months. Let's set the major ticks to 6, 30, 60, 90, and 120. Well, we have one more widget left, the push button for resetting everything. It's up here at the very top right in the middle. Let's drag it in and change its name to default settings. Now, align it. We have a nice looking gooey. Let's save it. Come to think of it, let's run it. It looks good. We built a nice-looking facade. But there's not much behind it. We need to make all these widgets work. We do that by writing code. By writing code, it's time to add some callback functions. Let's start with the radio button group. We right-click on the radio button group, and we need to be sure not to click inside one of the buttons themselves. This pop up appears. We slide down here and pick callbacks. We're presented with a choice of adding one of two callback functions, selection changed, or size changed. These names represent the events that trigger the calling of the function. We want to do something when the user pushes the button, which is what selection changed means. So we pick that. Here we are back in the code view again. The app designer has served up a callback function with a rather long name, DataSourceButtonGroupSelectionChanged. Matlab came up with his name by jamming together the text of our label, which is data source, the type of the widget, which is button group, and the event that triggers the call, which is selection changed. This is the standard approach for generating unique callback names, and you need to learn to love them because you can't change them. As you can see, since the callback names are in the gray area. This callback function has two input arguments, app and event. The first argument is the app object itself. The second argument, event, contains information about the action that triggered the call. Let's set a break point right here at the only statement in this function and run the app so we can see a callback function get called automatically. I'm going to run it without saving. I'm doing that for two reasons. One, in recent installed versions of Matlab, clicking Run causes an automatic save. Two, I'm lazy. Now I'm going to click the MonthlyRadioButton. MATLAB is going to determine that I clicked a radio button in this group, it's going to check to see whether there's a callback for this widget, discover it, and call it with two arguments: the app object that we've been building, and the event object, which we'll look at in a few minutes. Three, two, one. Click. Here we are at the breakpoint. What's about to happen is an assignment of app.DataSourceButtonGroup.SelectedObject to a local variable that MATLAB provided us, called SelectedButton. On the right, the first.operator is doing the same thing we saw it do in the lectures on object-oriented programming. It's selecting a property of the app named DataSourceButtonGroup, which is another jam together name, and it's also an object. The second.operator selects a property of that object named SelectedObject. Wait, the last time we looked, this app had four properties, UIFigure, UIAxes, which the app designer included, and temperatures in TimePoints which we added. Has the app designer added a fifth property named DataSourceButtonGroup? Let's check up here in the properties and see if it's there. Cowabunga, look at all these new properties. There's one for every widget that we've added, and the labels have them too. There's one for each of the buttons in a RadioButtonGroup. Right here is what we're looking for, DataSourceButtonGroup. That property holds a handle for the RadioButtonGroupObject. On the right, here is all this lovely brown stuff. Do you remember this from our object-oriented programming lectures? These are validations for these properties. In particular, these are built-in classes, and when a value is assigned to one of these properties over here, MATLAB immediately checks to see whether its class is the specified class over here or a class that can be converted to the specified class. For example, if the specified class over here were a double, then you could assign any number to the property value over here, like say an int eight. It would be okay because it can be converted to a double. But you couldn't assign a cell to the property because the cell can't be converted to a double. That booboo would throw an error and stop the whole app in its tracks. But we don't have to worry about assigning the wrong thing to these properties. They're assigned values by the app designer itself, so we don't actually have to worry about these validations. But since you're the curious type. I know you'd be pestering me to find out about them, so there you go. I sense that you're also going to pester me about all these dots in the class names. Well, that's something we haven't discussed and it's a bit different. To explain, it requires a brief digression. You can define a class inside its own class folder, which has the same name as the class itself, but prepended with an at sign. That folder can be contained in the so-called package folder, which can have any name as long as it starts with a plus sign. Told you, like I said, it's different. Packages can be inside packages and to access the class, you give the top package name a dot, to sub package name a dot, and so on until you get to the class name, and you drop all those plus signs and the at sign from the names. That's how we get these long names with dots in them. If you want more on packages, you can search the documentation for the phrase packages, create name spaces. If you don't want more on packages, that's okay too. We don't need to know how they work to make a GUI. But I digress, like I said. Back to business. DataSourceButtonGroup is an object with its own properties, and one of them is named selected object. When we clicked on the MonthlyButton and the RadioButtonGroup selected object was automatically assigned that button. It's one more thing done by MATLAB in the background. Let's hover the mouse over that selected object property to see what's in it. This pop-up shows that it holds a scalar object of the class matlab.ui.control.RadioButton, with three properties. Which are starting from the end: position, which contains coordinates in pixels of its upper left and lower right corners; Text, which holds the label that we gave the button, monthly in this case; and value. You'll find that every widget object has a value property. You can use that value to effect the behavior of the app. The pop-up says that value contains the number 1 but I know better. If you check the value type, you'll find that it's logical, so its value is actually equal to true. True here means that the "Monthly" button is the one that's currently selected. I'm going to go up here and "Quit Debugging", pop some code into this callback function, and then explain it. 1, 2, 3, pop. We're not using the first line so let's delete it. This code comprises a single switch statement that checks the value of the SelectedObject property of the button group. If it's equal to MonthlyButton, then "Monthly" is the button that the user has pressed. In that case, we print into the command window the phrase, monthly pushed. We print a similar message if the SelectedObject is equal to MonthlyAverageButton or BothButton. Let's clear the break and run it, and let's click the "Monthly" button and get the app design out of the way so we can see both our app and the command window at the same time. There is our printout. Let's push the other buttons. It's clear from this that pushing a button causes its object to be copied into SelectedObject, and then causes the callback for the radio button group to execute. If we click the same button twice or more in succession, nothing happens, and that makes sense. The name of the callback function is DataSourceButtonGroupSelectionChanged after all, so unless we change the selection, it shouldn't get called. Then it doesn't. Now I'm going to shoot some new code into this function to show you that there's another way to determine which button is pressed. 1, 2, 3, [inaudible] Here we take advantage of the fact that each radio button has a value property. That value is set to true if and only if that button is the one that was pushed, so we use this if elseif statement to find the button with the true value. Does it work? Well, we're going to let you try this one on your own. In the meantime, let's investigate the event argument. Let's put our break back in and "Run", and let's click a button, and let's hover the mouse over event to see what's inside it. Well, it's an object of course, and it has four properties. You can easily guess the meanings of these properties: the first one is the button that had been selected before the current button was pressed, the second one is the current button, which is the one that causes function to be called, the third one is the button group as a whole, and the last one is the name of the event. Because of the availability of both the previously selected button and the current one, event gives us more capability than the other options we looked at. But for our purposes all we need is new value. Here's an example of code that uses that. Here again, we use a switch statement and we're determining which button is stored in NewValue, and that's all that is to it. I'll let you run this one too. Now it's time to do something better than printing debug messages to the command window of which we do exactly. We have two possible plots that we want to show the user, the monthly data and the monthly average. Let's introduce new properties that we can use to determine what needs to be plotted: ShowMonthly, and ShowAverage. We'll scroll up to where we added the temperatures and the time points and add these new properties right there. You could also do with the "Property" button again, but we don't need to this time because we've already got a properties group that we can edit. Let's not forget to initialize these properties in the startup callback. When we start, we should set them according to which radio button is pressed in our initial setup. As we've seen, that can be determined by looking at which of the button's value properties is true. Here's code that does that for us. Here we're using the OR operator so that if the MonthlyAverageButton is pressed or the BothButton is pressed, we set ShowAverage to be true, otherwise, it sets to false. Here if the MonthlyButton is pressed or the BothButton is pressed, we set ShowMonthly to true, otherwise, it sets to false. We've got the information we need to determine what the plot. Right now our plot shows only the monthly values but we'll fix that soon so that what it shows depends on the values of ShowAverage and ShowMonthly. Now, let's get back to doing something better than printing debug messages to the command window. Let's replace the code that prints with the code that sets ShowMonthly and ShowAverage according to which button was selected using the same logic that we just did with the startupFcn. That's good, but there's something missing, in fact, multiple things are missing. First of all, the user has just changed what must be plotted so we need to refresh the plot. Also, we are currently plotting only the monthly data in the startup function and we need to plot both monthly and monthly average when the app starts. Our other widgets affect what should be plotted as well, we certainly don't want to have separate plotting code sprinkled all over our app, so it's time to write a new method, a function that does the plotting. We don't need a callback, we need a normal method that callbacks can call when they need to plot the data. So how do you add a normal method? The answer to that is up here at the left of the Property button. There are a couple of blue buttons there: One for adding a callback and one for adding a non-callback function, we want the non-callback variety, which is labeled Function. Let's click the little arrow below the Function button, and we're given the option of defining a Private or a Public Function. Since the plotting method will only be called from within the app we'll choose Private. Let's change the name to plotData, and get rid of the output argument because we don't need it. Now, we'll just move the plotting code from the startupFcn into this function. What about the monthly average? What if we need to plot both? Here's what I'm thinking at this point. We could compute the monthly average here, for the ShowAverage option, but plotting the average and calculating average are two distinct functionalities, so it makes more sense to have separate functions to handle these two tasks. Also, it would be inefficient to recompute the average every time we need to make a new plot, the only time we need to recompute the average is when the length of the window over which the moving average is calculated changes. For these reasons, it's better to have a separate function for computing the average, and it's also better to store the average in yet another property of the class. So let's add one, and let's add a method called compute averages, we can put it right after the plotData function. Here, we call the built-in function named movmean to calculate the average. You may remember that this was the function used, well, used indirectly to calculate the moving mean of the CO2 levels in our lecture on live scripts in lesson 3. The second input argument to movmean is the width of the sliding window, that width is supposed to be set with the averaging window slide, but we haven't got that thing working yet, so we're just fixing it right now at 30, and we put in a comment here to help us remember that we need to change this later. Now back to the plotData function. Let's add code to the body of that second if statement. We plot the data in averages and we do it with a red line of width 2, we need to make another slight change though, we need to add a hold-on and a hold-off, like this. We have to do that so that if both plot commands are executed, the second one won't obliterate the first one, and we need to turn hold-off at the end so that the next time around we'll start with a clean slate. We're using a version of Hold that allows us to specify the axes in the first argument. Now we can call this function from both the startup Fcn callback and the radio button callback. Let's add those calls, first in the startup function, and there we need to call the computeAverages function too, and then in the radio button callback. Let's run the app. Let's try changing the plot with the radio buttons. It starts up correctly, the axes and radio button widgets are working and we've got a good layout. While we got it running, look at the title up at the top of the application window. Not very informative, is it? Let's change that. Click "Design View." Click anywhere in the app that's not inside a widget. Now, over here in the component browser, look down here at the bottom, click "Identifiers" and find the name field. All we have to do is replace the text in the window with the name we want. How about Berkeley Earth Global Surface Temperature Estimate. Let's give credit where credit is due. Let's run our application again, and there's the new name on the window. Now looks much better, and while we're on the subject of looks, our app is looking gray; don't you think? We should add some color. Let's click again anywhere in the app that's not also inside a widget. Now over here in the component browser at the top, we see our new app name, which as usual is formed by jamming all the words together, and down here in the WINDOW APPEARANCE section, we find color. Let's click this little square, and we'd see 28 colors to pick from. Actually, you've got a few more to choose from the [inaudible] , 16,777,216 to be exact. We can probably find something you like in there. You've got several ways to find colors in addition to picking one of those 28. I like to pick one of the 28 to get into the ballpark and then click this little stripy box. That shows me on the left a two-dimensional range of shades near the color that I picked from the array of 28 and a rainbow on the right that lets you change the range you're looking at on the left. Let's see. I like this bluish gray shade. You can go down here to the RGB area and see the fractions of the pure additive primaries, red, green, and blue, that are being used to produce that shade. Another way to pick a shade is to type in the fractions you want for each pure color directly. Whereas zero means none of that color, and 1.0 means as much of that color as possible. Let's try 0.35, 0.55, and 0.65. There, I love this color. It's not too dark for the black text and not too light for the knob tick marks. Not too dark, not too light, just right. We're in the Goldilocks color zone. You can switch from fractions to absolute values on a scale of 0-255 if you want and you can even change from RGB that is red, green, blue to hue saturation value if you enter "HSV." There's one other option here labeled Hex. When you choose this, you can specify all three color fractions with one hexadecimal number, and that can be surprisingly a big help if you're not sure what colors to use. Some people are colorblind and some people, how to put this, have a bit of a problem knowing what colors go well and what colors just well don't. At the risk of offending most of the students watching me right now, there I said it. Engineers on the whole seem to have this problem big time. I'm talking about people that think that bright red looks just great right next to bright blue. While we're at it, they might add a bright yellow border around both of them. Humanity. To avoid this problem, just go to a website that gives color schemes. Like for painting rooms, or coordinating furniture, or clothes, or something. These companies hire people with taste like me, and some of their websites give you x values that you can copy from a color scheme, paste them in, and then a few clicks the most hideously ugly app will be magically transformed into a beautiful work of art. Well, maybe not art, but at least the colors won't clash. But we're going to stick with his lovely blue gray and add one other color, and we'll call it a day. By the way, two colors is plenty for most apps. If you must go to three, think hard before you do. Let's click inside the axis and click on Color and Transparency Maps, then scroll down to Background color, and click it square box. I'm going to cut to the chase and type in the fractions for a tannish gray shade that I've found before I started recording this lecture, 0.78, 0.76, and 0.73. This shade looks great with our bluish gray. Now, let's give the radio button group the same color as the axis, to make it a theme. First, I'm going to double-click inside the background color box for the axis here, and use command C to copy it. Next, I click inside the radio button, double-click inside the background color again, and use command V to paste. I hit Enter and the color is set. I'd like to color the knobs too, but aside from the label font, the app designer doesn't allow that. So I'll settle for having a tarnish gray default settings button. I can do the same thing with that button that I did with the radio button. But I'm lazy as you know. So I'm going to resort to magic for that. Color code turn, a very funny okas, very funny. Color code turn, there. We've got a tasteful color scheme. I wish the button group were aligned vertically better with the knobs. I can move it around manually. But that seems I don't know too manual. Instead of that, let's click about here, hold down the left mouse button and slide the mouse to expand this rectangle to capture those three widgets, which you can see by the highlight around their borders, and go up here to just below the word Canvas on the ribbon, and select the lower-left icon, which shows things being aligned on their top edges. We click that, and these three widgets line right up on their top edges. Friends in my book, this is now a perfect app. Well, except for the fact that most of the widgets aren't working. Let's run it again. This time I'll show you how you can squeeze and stretch it, that she didn't know you could do that, and we didn't have to write any code to make it happen. At this point, you've learned the fundamentals of designing an app, which is an application based on a graphical user interface or GUI. We've introduced you to the two fundamental concepts of the GUI, which are the widget and the callback function. We've shown you how to use MATLAB's app designer to build a GUI with them. We've used this design view to choose and range widgets for an example app, and we use its code view to add code to the class definition automatically produced by the designer that makes things happen when the user clicks inside these widgets. Our example app isn't done of course, but there's lectures covered all the basics. In the next lecture we'll get all our widgets working. Then in the lecture after next, we'll turn this app into a program that can be run outside of MATLAB.