 Hey, folks, I'm patch loss and this is code club. In this episode, I'm going to talk about how we can animate two plots that are in the same figure. How do we do this? Well, we're going to use a package called gg animate that's being developed by Thomas Lynn Peterson, who also developed patchwork, as well as David Robinson, who was the original developer of this tool. We're going to create a gif. And I've been wanting to make this figure for only forever. And and considering this is the 100th episode of code club, I thought this was a pretty cool opportunity to release and create this figure to share with you in the world. If you've been following along in recent episodes of code club, you know that we've been developing this figure, which is where we ended with using Thomas's other package patchwork to create a panel that has the inverse Simpson index on the left side for three groups of people that either have that are healthy, or that have diarrhea and are cdiff negative, or that have diarrhea and cdiff acetyl positive, as well as then on the right side, we have the receiver operator characteristic curves using a high level of inverse Simpson diversity to indicate health. Now what I found is that people don't always know how the data on the right these rock curves with sensitivity and specificity link back to the data on the left side the actual data that we are using as the biomarker. Rock curves are a tool that my lab uses frequently to assess the performance of different models or different biomarkers that go into those models that are used to classify different disease statuses of patients based on their microbiome, their demographics or other health characteristics. Here is an example of a slide that a former student my lab named Neil Baxter created. The data on the left is similar to what I had for inverse Simpson, but this is a measure of the amount of blood in a person's stool. You don't want blood in your stool. And the right is using that measure. It's called fecal immunochemical test as a biomarker for the presence of lesions in a colon or cancer in the person's colon. And so as you can see, as you kind of go up, then you're more likely to have cancer. And so again, what Neil did was that again, recognizing this challenge linking the data on the left side to the right side. He made a series of slides that looks like this. And you can kind of see they're not always in the same position. So they jump around a little bit. But he's got this horizontal bar here that I really liked, because it shows you basically where the point is on the rock curve, as we kind of step through bringing the threshold down the values of the amount of blood in the stool sample. And again, we can kind of keep stepping through and we get to the end of the animation. So this isn't really clean or polished. It's it's pretty hard to recreate this. We created for colon cancer. But if I wanted to use it for C. difficile or for something else, it would be hard to generate. And I've always wondered, you know, could we use our to generate this type of animation so that it's dynamic, and we might even be able to like, you know, put it up on a website and so that I don't have to be there kind of paging through the different slides in a talk. So that's exactly what I want to talk about in today's episode. So what I'm showing you here is the chunk of code that I'm going to start with, it's similar to what we've been working with in past episodes, you can get your own copy of this by going to the blog post that's linked down below in the description. Also, if you want help getting things set up across the top here, I'll put a link to an episode where I described how to install our studio the tidy verse and get the data that I'm working with so that you're all good to go and you can follow along. I'd certainly encourage you to get the code. So you can use it with your own data, you can use my code and experiment and try different things. Like I said, this is similar to what we've done in the past. Let me go ahead and load everything and run it and show you what this will generate. So this is the figure that's created from that code. On the left, you see the strip chart showing the inverse Simpson index for people who are healthy and those who have diarrhea and who are seed of positive, as well as the receiver operator characteristic curve of the sensitivity and one minus the specificity based on using the inverse Simpson index to predict whether or not somebody is healthy or has see difficile. Again, what I'd like to do is I want to animate drawing a line going across here. And then linking that to like a ball on my rock curve. So as the line goes up in the strip chart, the ball by animation goes across the receiver operator characteristic curve. I think we can do this using the Gigi animate package and it'll be pretty slick coming back to my code. I'm not going to be using patchwork going forward. I am going to be using Gigi animate. And so if you don't have Gigi animate installed, go ahead and install that. We'll also want the magic package. So I'll do library magic. And that's I C K. And so I'll load both of these packages to make sure we have access to their functionality. So reading through this code just describe what's going on. We're setting the seed for random number generators so those jittered points don't keep moving every time we run it. We're loading the data. We're joining the data. We then have code in here for generating the rock curves, whether that's getting the sensitivity and specificity or creating the actual curve itself. And then down here I'm setting the test the comparison that I want. And then we are filtering the data to get only those curves or those points that correspond to the test of comparing the non dire real control to the cases. Again, the cases are people that have C difficile and have diarrhea. To give you a sense of what test data looks like, we can see that test data has a column with the disease status, the inverse Simpson index for that person, and then the sensitivity and specificity for that inverse Simpson value, as well as information about the comparison and the negative value as well as the positive value, the negative being the non dire real control. And in this case, the positive being the case. Then we have this diversity plot where we are creating a strip chart that shows in one column the inverse Simpson for the healthy individuals and in another column the inverse Simpson for people that have C difficile. Then we have a plot for rock for creating the rock curve where again we're plotting one minus the specificity on the x and on the y the sensitivity and we're grouping the points by comparison and we're getting this black line. And again, if you want to learn all about this, look at the previous episodes and you'll see what we did. And in the last episode, we talked about using patchwork. And here is the syntax and patchwork that got those two plots right next to each other. So I'm going to start by removing these two lines. We're not going to be using patchwork or gg save in this episode. Let's start with the rock plot the receiver operator characteristic plot and see if we can't animate that a couple things that we want to do. We want to maintain the rock curve, but we want a point to move across that curve. So what it's going to animate is what data is coming into the gg plot function. If I want it static, I can't define it in the gg plot function. So as you'll see gg plot here is using test data as input to gg plot and then it's using the aesthetics to get geomline going. So what I need to do is I need to create a separate data frame that I can use to indicate all the different points that my ball is going to be positioned on. So if I do test data and then I pipe that into a select where I'll do in Simpson as well as sensitivity and specificity. And I'm going to rename those because I don't want to have the same column name in two different data frames that I'm working on. So I'll do rename and I'll do inverse Simpson. Inverse Simpson underscore step equals in Simpson. And then I'll also do sensitivity sensitivity step equals sensitivity. And I bet you know what the next one is specificity step equals specificity. And I'm going to go ahead and call this stepper. I'll call it step data. And so now if I look at step data, I see it's a data frame that's got the inverse Simpson, the sensitivity step and the specificity step. So the inverse Simpson step you can imagine that that's going to set where the bar is the horizontal bar as we go through and the sensitivity and specificity step columns is going to control where that point is in our rock curve. So what we can then do is modify our rock plot so that geom line is going to use the aesthetic data or the argument data, and that's going to take test data. And then we're going to have mapping equals and that's going to be the aesthetic that's already here in GG plot. And that looks good. And the GG plot now needs and not test data, but we'll do step data. And our AES I'll do x equals and that's going to be one minus specificity step and y equals sensitivity. Right. And that looks good. And I'm going to go ahead and then add geom point. And we will then so that will use this aesthetic information it'll use our our step data so that needs to be sensitivity step. And I will do PCH equals 19 which will give me a solid circle and I'll do size equals five. So I want this to be a big circle and I'll do color equals orange. Let's go ahead and run what we have right now and see what this all looks like. It looks like I've got a typo somewhere in here. Yeah, so I've got an extra parentheses there. And we see that we have our black line for the rock curve, as well as what looks like a really thick orange line, but that's actually the ball. And I'm going to move geom point to be in front of the line. What we have now is our black rock curve covered by those orange balls. And so it looks like again like someone took an orange magic marker over the top of our rock curve. But what we are going to use GG animate to do is to animate the position of those balls and make it really easy and the syntax builds off of what we've already got with GG plot. And so I can add to the end of this here my line 127 after my geom rich text, I can say transition underscore time. And that then the aesthetic that I'm going to match to the time and kind of the interval of placing those different circles. I am going to put in the Simpson step. And so at each value of inverse Simpson value, it's going to step in putting in a different ball. So now what I can do is I can say rock plot. And this now takes time to render. It looks like it's going to take maybe 10 seconds or so to generate the gift. And then over here in my viewer, it is then going to show my gift. And so you can see my orange ball going across my rock curve. One of the nice things about transition time is that a side effect, it outputs the value of the variable that we're stepping through as a variable called frame time. And I can then use that in like a heading. So I could then say labs title equals and then in quotes I can use my glue notation to do frame underscore time. So at the top left corner now as part of the title, you can see the inverse Simpson value that it's stepping through, right? I could go ahead and make the title, you know, a little bit fancier, but I'm going to hold off on that for now because I don't really care. Some place that I've seen this as if you were familiar with like the Gapminder data, or I've seen this with like the COVID data, where perhaps you have a map, or any other type of plot, where each frame then is like a different year or different day of the month, or different day of the year. And you kind of step through the animation and in the upper left corner, then you can then put in what date is it. So again, that's, that's a pretty handy output from transition time. You should also know that there's other transition functions that you can use with GG animate. And I'd encourage you to play with those. I'm only going to be working with transition time today. Also, you'll find that there's different ways of kind of easing in and out of positions. Again, for my purposes, I think this transition time does a great job. And I'm going to leave it there for now. Next, I'm going to turn to my diversity plot. And to do that, I'm going to grab this chunk of code that I used to create my data frame step data. And I'm going to go ahead and put that up here ahead of diversity plot. And in this chunk of code to create diversity plot to animate it, I'm going to want my strip chart to be static. And I'm going to want this horizontal line to be dynamic. I want that to be animated. And I'll generate that using geome h line. So again, we're going to have to do the same type of thing we did down below with the rock curve. So what I want to be static, those data frames and aesthetics have to be defined in the geome. What I want to be animated, that needs to be defined in GG plot. So how do we go about doing that? Well, again, it's going to be very similar to what we just did with the rock curve. So I'm going to grab this aesthetic mapping. And I'll put test data, say data, data equals test data. And then mapping equals the aesthetic. And so I've got that in good shape. I'm going to go ahead and then make test data, step data, pipe that in a GG plot. And then what I'll do down here is I will then do geome h line. AES y intercept equals inverse Simpson step. Make sure I get a plus sign at the end of that diversity plot. That then shows me you can maybe make out in the background the strip chart, but then I also see all those different lines. Now, we're going to do a very similar thing that we did earlier with the rock curve here, which is to do transition underscore time and then what I'm stepping through. And that's going to be inverse Simpson in Simpson. It's easier to say inverse Simpson step and go ahead and load that if I go ahead and then do diversity plot. This will again go through and take about 10 seconds or so to generate the gif, animate it and then pop it over in my viewer. And so we can see our gif right where we've got our strip chart and we've got our horizontal line going up across our different points in the strip chart. So it's exactly what we want. So when I run, say, diversity plot, it generates this gif for me automatically. I can have better control of like the dimensions, the resolution, the number of frames, the speed, all sorts of stuff using the animate function. So I'm going to say diversity gif animate and I'm going to tell it to animate the diversity plot. And I'm going to say n frames equals and that's going to be the number of rows in my step data frame. So I'll do n row step data and I'll go ahead and do width equals this is my diversity one. So I'll say three height equals four units equals inches. It's important when you're working with these gifts that our gifts be the same height as each other. And then I'm also going to do res equals let's say 200. And then I need to do renderer. And this tells gg animate how to render the plot as a gif. So I'm going to do magic underscore renderer open close parentheses. Now for my rock curve gif, I'm going to do the same thing. So I'm going to copy this down instead of diversity dot gif. I'll say rock and instead of diversity plot, I'll say rock plot. But I want the same number of frames because I want those to be synchronized. I'm going to make the width here for width for height for so that it's square. Same resolution same everything. I'm going to keep working with these two objects diversity gif and rock gif to put them side by side. But if I wanted to save these I can use the function anim underscore save. And I can then say I want this to be saved as diversity dot gif. And I'm going to save the object diversity gif to that. And same goes here. So I can see both gifs in my browser. Again, this is the diversity plot gif. And then this is my rock curve gif. And so you can see these are quite a bit higher resolution than what I had in the viewer over in our studio. The next thing I want to do is I want to take these two gifs that have something like 240 frames each and frame for frame. I want to put each frame side by side with diversity gif on the left and rock gif on the right to do that. We're going to use a package called magic, which is an R implementation or our interface to the image magic package. It's a really versatile tool that you can use an R as well as from the command line. I use it for doing all sorts of little things for kind of cleaning up different images, whether it's making images square. So like all the pictures on my lab website are square rather than rectangular. It does that removes the backgrounds that converts between different formats. It's really powerful, but it will also allows you to put images right next to each other in a new image. We're going to create a variable called new gif and it's going to be image append. And that then takes a vector of two different gifs. Now diversity gif and rock gif are basically you can think of or I think of as a vector of PNG files. And again, we want to get, you know, the first, the second, the third tied together. And so we'll do diversity gif one and then rock gif one. So that creates new gif and it seeds new gif with an image. What we now want to do is loop over all of the other images to make a big new gif. And to do that, we're going to use a for loop. And so we'll do for I in two colon and we're going to do Enro step data. Right. And so that will then go through all of the frames in in the gifs. And we can then do combined. And that we're going to do image append like this. But instead of one, we're going to put eyes and then new gif will be the combination of the original new gif or the new gif from the previous iteration along with combined. We can then save the output here again with anim underscore save and also save this as diversity rock gif. And the object we're going to save that to is new gif. And let's go ahead and run all this and it'll take some time to again do all that appending and rendering as a gif. And then we'll check it out in our browser. Wonderful. I think this works really well. You can see on the left the horizontal bar I was after kind of going up across the different values of the inverse Simpson index. And on the right, you can see my orange ball going across the receiver operator characteristic curve showing you the sensitivity and specificity for each value of the inverse Simpson index. I'm really happy with how this turned out. It's so much better than that PowerPoint animation that we had been doing. I could put this on a web page. I could probably even post this to Twitter when I announced this episode. One problem is that this is about 14 megabytes. So it's pretty big. It's seven inches wide. So it's bigger than your typical meme gifs. If you want it to be smaller, of course, you could play with those dimensions and make them smaller and play with the resolution a bit and probably the number of frames that are in here. The default is 100 frames. We're doing about 240 250 frames so that each inverse Simpson value really gets more or less its own frame. There's a lot you can play with in GG animate to make all sorts of different animations. I really encourage you to use the approach we used in the last episode to learn about patchwork to learn about GG animate. It's from the same developer and he's done a really nice job of putting together documentations and some vignettes to help you learn how to use GG animate. I think this is really cool. And while gifts can perhaps be overwhelming and be used too much. I think they really add something really nice to a visual like this, especially in a presentation where I can easily show my audience how the inverse Simpson values on the left relate to the ability to make a classification on the right. Anyway, let me know what you think of this animation down below in the comments. I thought this was a fun way to showcase some really cool things about our for a hundredth episode. If you watched all hundred episodes, I would love to hear from you. If you're one of those people that have seen all hundred, give give us your name down below so we can give you some applause. That's really awesome. I really appreciate all the support all the input people have been giving me all their enthusiasm. It really makes me happy to see so many people benefiting from these videos. I have a lot of fun doing them so it's not even like work for me and I'm learning a lot as I do it as well. Please keep the feedback coming. Think about this with your own research. Are there different applications where you could imagine using GG animate to maybe kind of spice enough a figure, perhaps make something more clear. Of course, this isn't going to work in a manuscript, perhaps, but certainly could work quite effectively in a presentation. And I guarantee you people are going to be impressed with your gift skills. Anyway, keep practicing with this. Again, see if this works with your own data. Tell your friends about what we're doing here and we'll see you next time for another episode of Code Club.