Transcripts
1. Introduction: Hi, my name's Nicholas Felton. I'm an information designer based in New York City. The bulk of my work is around doing data visualization based on personal data, or on other data sets that I find in the world. I started working with data about 10 years ago. As a graphic designer searching for stories, I found that the one I had the best access to was my own, and it was easiest to collect this in the form of data. The data visualizations come out of this as a way of representing these stories in a compact and interesting way. My investigation of personal data has largely been driven by curiosity. I have this desire to know the unknowable, it's almost like being an explorer. I'm influenced by sort of science, and math, and geometry, minimalism. This class is going to tackle one of the things that I find the most interesting, which is taking a really enormous data set, one that you could never manage by hand, and placing all those points onto a map. In this case, we're going to look at meteorite strikes around the world. We have a data set of about 34,000 points, and we're going to stick these all on a map, and label the top site. I think this is fundamentally a design class, but it should also be a really good introduction to processing. I hope it'll pull down the curtain a little bit and show people how easy it is to get started, and how much power you have to manipulate your designs using processing. We're going to work in three different areas today. One is going to be about looking at the data, investigating a little bit in a spreadsheet, and then moving into processing. Here we'll do the bulk of the work, where we'll be setting up a program that can parse the data, and project it onto a map. Finally, in Illustrator, we'll be cleaning it up a little, and showing some of the ways that we can tidy it up and fix some of the issues. You don't have to be a designer to take this class, you merely have to have some curiosity or interest in starting to turn a table of numbers into something that is really consumable. I've chosen the data set and written the app that I'll walk you through. This will ensure that everybody can make it to the end and have the same results, and we'll also have a template for working on other data that you might find in the future. In the documents for this class, there's a couple other sources where you can find extra data sets if you want to play with those. Historically, designers have worked with text and image, and I think that because we're living in this world of data everywhere, it's become this new fundamental element of design that designers have to become so much with.
2. Your Assignment: Your assignment is to visualize a large set of meteorite data as a map. I've included the dataset here, so you can download it right away and get started. What I'd love to see people upload Skillshare at the end of the course is a PNG or a jpeg taken from Illustrator of your final laid out map of these meteorites strikes. There's a little bit more data in a meteorite strike set that you could use to push this further. I can imagine color-coding the meteorite strikes by the year in which they happen from oldest to newest. There's also extra datasets that you could look at and start to investigate other maps from different sources. The way to achieve the most success with this class is going to be re-executing the lessons in processing as I demonstrated them. You'll have the completed application and you can make sure that you have a working end-state, but actually working up to that, and understanding the different sections that we went through to get it working properly will teach you the most, and put you in the best state for being able to explore other data or apply this in new ways.
3. How Processing Works: Before we get started making this map, I'd like to share some key concepts that will come in useful as we go through the lessons. The first is about data formats. So, we're going to start with a spreadsheet. A spreadsheet is a way of showing data in rows and columns. What we're going to need to do to bring this into processing is converted into a different format called a CSV. CSV stands for comma separated values, and basically all we're doing, is rather than having explicit dividers in the app which separate these rows, we're going to substitute those for a comma in a space, and then it will just be a text file, one that you could open in TextEdit. We need to put the data into a CSV format because, this is what processing expects to ingest. It removes all the extra formatting that a spreadsheet can have attached to it, and simply strips it down to a plain text format. Once we open processing, you'll see there are three main components. There's an editor, a console, and the canvas. We'll start in the editor. This is where all code gets typed. The console can then be used to print out little bits of data to make sure that everything is running smoothly, or to find problems in our code. Finally, the canvas is the area in which we'll be drawing things. This is what we'll ultimately save to a PDF. We'll be writing the code and processing in the editor. Like HTML, there's a hierarchy to the way that code is written, and there are three main areas that we'll be dealing with. Above everything is where we can define variables that we'll be using throughout the application. We can also import different libraries, if we were going to use someone else's tools that they've built for processing. Below that is a little area called set up. In here, we'll stick all the code that just needs to run once to define things that we'll be using in the app. Here, we'll setup the size of the canvas for instance. Below that is an area called draw. This is an area that will loop over and over unless we tell it otherwise. In this case we only want our sketch to run once, and so we'll put some code in there to tell it just to end as soon as it gets to the end of the draw section. Because we'll be working with data and processing, we're going to need several variables in which to hold it. Variables are just containers. This is what we're going to define to hold either names or numbers. In processing, we need to be explicit about what a variable is going to hold. So, we have to say this container can only hold this kind of information, or else we'll have problems executing the code. Some of the basic types of variables that you will encounter in this app are an integer, and this is defined by saying, int, and then the name of the integer, and then setting its value. With these basic variables. You can also have them print out their values in the console by introducing this code, the println function. So, for this initial example of an integer i with the value of zero, if you put this println line underneath, and you want to remove these two dashes that these two forward slashes, these are commenting it out. So, any code that you don't want to run, you can put these two slashes in front of it. That will print the value of i in the console. For more detailed numbers these are decimal numbers, we need to use a float. So, this has a different name because it takes more memory. So, if we wanted to save 0.0 or 2.895, we would use a float. Then finally, String is used for holding words. So, in this case, for the welcome variable that we're setting to hello world, we'll need to define that as a string. For larger sets of data, we can use a structure called an Array. Now, an Array is basically a list of data. These also have types. These can be integers, or floats, or strings, but they're set up with this racket syntax. An Array called numbers, in which I want to store zero, one, two, and three, is defined in this way with the brackets up front, and then the braces to important numbers. Basically, what we wind up with is a multi section container. This Array now holds zero, one, and two, and then we can either print all of them, by saying printIn i, which will just print the entire list, or we can use this bracket format to get it any of the positions in our Array. So, people bracket zero would be the first one, this would be Mark in this case, or people bracket one, would be any and so on. The final data structure we'll encounter is a 2D Array. This is a list of lists or a matrix. So, if you think about the Array that we just discussed, this is now going to be one that holds several other Arrays. So, rather than having one bracket after the type of data that it holds like integer bracket, which is how an Array is defined, this one requires two. Now we're getting back to this spreadsheet idea. We are talking about columns and rows. As you can see in this matrix, we have our first row, that's denoted by zero because this is how computers count from zero up. We have the row one, and the row two. We also have the columns zero one and two. Now, if you look at how we define this matrix of data, with three Array functions, you can then use this println code to access different parts of it. I've highlighted in the matrix, what will be highlighted or which will be selected by each of these lines of code. So, if we try and println numbers matrix zero, zero, we'll get the first position. While if we do println numbers matrix two, two, we'll get the last position. Now, we apply all this data in processing, we'll need something that will be able to loop through it and call all of these different bits of data out of memory. So, we're going to be bringing in the names of these meteorites and their latitude and longitude, and so, we use a for loop to cycle through all this data. A for loop is something that can look a bit intimidating upfront, but it's simply a structure that gets used over and over when you're doing anything in processing. It looks a little bit intimidating because it's a really condensed piece of code. What's happening here, is we're saying that we want an integer i, and we're going to set it to zero. Then, as long as that Integer is less than three, we want to add 1 to it. This i plus plus, is the same as i equals i plus one. So, while those conditions are true, then keep doing everything within these braces. So, we can play this out manually. So, the first time this runs, i will be equal to zero. So, for each of these print lines we can imagine replacing the i with a zero. So, the first time we run through we'll be printing zero zero, zero one, and zero two. When we get to the end, we will add one to i. So, now will be running through it with i equal to one. So, we'll println for one zero, one one, and one two. Finally, we'll add another one, and now i will be equal to two. We'll run through it again, and print two zero, two one, and two two. Then we'll add one, and it will be three, but it won't meet this condition of being less than three. So then, the for loop will end. This is just a structure that you'll see everywhere in processing, and we'll be using it today.
4. Geometry of Maps: One of the the other concepts that we need to to get a grip on is how to measure Earth. Earth is a sphere, and the only really accurate way of showing this is with the globe. But we need to flatten it onto a 2D surface to get it onto our screen. So, the Earth is measured in two dimensions, latitude, which is the horizontal bands around the Earth, and longitude, which are the vertical bands. They're a little bit tricky because the scales don't started at zero. Latitude is 90 degrees at the north pole, and negative 90 degrees at the south pole with an equator of zero. So it spans 180 degrees. Whereas, longitude, which needs to wrap around the whole world has to cover a scale of 360. So for this, it goes from minus 180 to 180 with zero being defined at Greenwich in England. Now to flatten this, there are many different ways of projecting a sphere onto a flat surface. If you go to Google image search and look at map projections, you'll see any number of different ways of doing this. Today, we're going to use what's called the equirectangular projection. This is by far the simplest way of turning a sphere into a flat rectangle. You can also see some of the problems with using this approach. In this diagram, I have showed how if you have circles of different parts of the globe, when you flatten it out, you get different degrees of distortion using this projection. So, areas around the top and bottom of our globe are going to be really deformed. So, Antarctica will appear much, much larger than it is in actuality. But the math for getting this on the screen is much simpler than any other method, and this will be really useful for us. Finally, there's one more function in processing that will be crucial to translating this set of data into our glorious map. This is the map function, and what this does is it says that given the value that exists on one scale, translate that to the value on a different scale. So, you can see that this function takes five different inputs. The first one is the value that we want to translate. In this case, 127.55, and this is from the latitude scale, which goes from negative 180 to 180. What we want to do is translate that to our screen scale, which is going to start at zero and in this case is going to go to 400. So once we do all that, the map function will output a value along that scale. In this case, 341.7. So, we'll be using this for both translating our latitude and the longitude to the screen values we need. This map function is going to be invaluable for us as we try and convert the latitude and longitude of the Earth to the canvas that we're using. So, a canvas for this project might be 400 pixels wide. So, we'll take that latitude scale and convert it from 127.55 on the scale of negative 180 to 180, to 341.7 on the scale of zero to 400, the width of our canvas. We will also be needing markers to show the size of these meteorites relative to one another. One of the crucial pieces in this class is sharing this idea that when you convert quantity to area, you have to do a little bit of Math. So, it would be very nice if we could draw rectangles that we want to represent for by just saying both sides, the width and the height are four. Unfortunately, this translates to an area that is misrepresentative of what we want to show. So, the correct way of showing something with an area of four, is to take the square root of that area, and that gives us the dimensions of the square. So, to show four, we need sides that are two and two, not in this instance the sides that are four and four. So, the rule for generating a rectangle that's going to show area is to take the square root of that area and use that for the dimensions of the shape. With circles, the math is a little bit more complex. If you remember back to geometry class, the way to calculate the circles area is pi R squared. Because we want the area to represent our quantity, we need to backtrack from that. So, to get the radius of our circle, we'll take the amount that we want to represent, we'll get it's square root, and then divide it by pi to get the radius.
5. Exporting Data to CSV: Now we're going to get started with this project. Welcome to your dataset, this is called meteors. Once you've opened it up, you can start scrolling down a little bit to get a sense for the size here, this is something that no rational person would want to put onto a map by hand. If we scroll down to the bottom, you'll see that we've got 34,066 rows to this dataset. I always like to start in a spreadsheet like given a new set of data because this is where we can start to feel the bounds of what we've been given. You can see that there are six different columns here, each one's telling us a something a little bit different about our dataset. So, we have a name or a place for each meteorite strike, we have the year, we have its mass in grams, the longitude, latitude, and whether it was I think seen falling or if it was found. The great thing about spreadsheets is that we can do some real simple parsing of the data to get a sense for it up front. So, one of the first things I want to do is just see how many years this dataset span? So, the moment, I think it's set to be sorting in descending, I'm going to change that. So, already I can see some of these at the bottom don't have a year and this dataset goes to 2012. If I scroll up to the top, I can see this goes back to minus 600. So, there are some negative values in here to be aware of and it also gives you a sense of the duration of this dataset. By clicking here again, I can change this mass to be ascending or descending. So, I want to get a sense of what the sizes of these different meteorites are and if they all have values. So, at the biggest, we have this Hoba one with 60 million grams, and at the smaller end, we have ones that are down to 0.01 of a gram. The latitude and longitude is just going to vary within the bounds of the earth and fell_found seems like it's pretty straightforward, this might be something that's worth coding for later, but I think we've got a sense for the dataset and it's worth exporting it now into a format that processing can use. I think I'm going to want to bring in this data by its mass. So, I'm going to want to have the largest meteorites at the top of my CSV. To do that, I'm going to click on the top here and sort these masses in descending order, so largest up top. I'll just scroll to the top and make sure that's the case. Yeah, the Hoba meteorite is appearing on top. So, I don't have any extra rows or columns that are going to get in the way here when I export it, that would just lead to empty things I don't need. So, I feel good about the state this is in. Under Export, I'm going to export this to a CSV. I can leave the text encoding as it is, just hit Next and I'm going to save this to the desktop as Meteors.csv. Now let's just take a look at that, open it in text edit and see what this is turned into. Here we've got it, it's should be a 34,000 line long text file. You can see that all these columns have been translated now into comma-separated values with our first one appearing as the key telling us the place, year, mass, longitude, latitude, and fell-found. I'm just going to delete this top row because this is not data, it's just a key and I'll save it and we'll be ready to bring it into processing. I've sorted on the meteorites by mass because I'm going to want to label the largest meteors. This is going to be easiest to do by just saying, I want to label the first 10 or 20, rather than parsing all the values and testing them whether they're over a certain scale. This data can also be accessed in Google, there's a link on the Skillshare site for this set of meteorite size and data. This is a Google spreadsheet and here you can see some of the same information, these coordinates, there's even links to a database entry for the meteors. But if you'd like to download it here or explore it, you can sort things again by clicking on the top of the column label or under File by selecting download, you can download it as a CSV as well.
6. New File Syntax and Data Folder: If you don't have processing on your computer, you can get it for free by visiting processing.org. There's a big Download Processing button up here. Feel free to make a donation if you want, because this is open source software. Then download the correct version you'll need. So, I've got the Mac version already installed. But if you don't have it, just download it here. Once you have it installed, open up Processing and we're going to make a new sketch. Here, you should see some of the portions of the app that I discussed previously. We've got that empty Editor field and the console below. Let's just save this to the desktop. Let's call it meteorSketch, and you'll see this appear on the desktop. What we're going to need to add to this sketch is a folder called data. Now, not all processing sketches have this but if we're going to be bringing in external files like we will be, this is where it needs to live. So, just create a new folder in this directory and call it data with a lowercase d. If you've also downloaded the working example of this app that we're going to be building, you'll see that there's a data folder there, and it's got the two pieces that we need. It has the meteorite.csv and a file called WorldMap.spg. You can just copy over these files into your data folder or you can use the meteors.csv file that we generated earlier. So, in your meteorSketch, you can already hit Run and you'll see the canvas pop up. We're going to need to start by setting up the draw and the setup sections of our out. So, you can either type these indirectly or you can open up the reference sketch that's provided on the Skillshare file. In here you'll see the little commented out label that I use to indicate the beginning of the setup section, and underneath that we'll just need to say void setup with some parentheses and a open brace and a close brace. Then we'll also have this commented label to indicate the beginning of the draw section. In here, we can say void draw, then open the brace and close the brace. Up above, I'll just make one more indication of what will be there. This is where we're going to put both the library we'll need and the global variables. So, this is the skeleton of our app. This is where the pieces that we're going to need will be living. You can hit Run again, and you'll see that same little square happening. So, every time you hit Run, it's going to check your code and make sure that there's no errors. So, we're in good shape. Let's save this and start bringing in some of the basic elements we'll need. In the setup section, we're going to find things like the size of our project, we're going to import the map that we'll be using, and these are things we just want to happen once down below in the void draw section. This is where you can have code that runs over and over and over again. So, if we were making an animation or an interactive, we want us to keep drawing frames on screen. The main thing we're going to want to happen in our draw section is we're going to want it to start saving a pdf at the beginning, and saving it at the end. So, we just want that to run once or else we'll wind up with a pdf being saved over and over and over again.
7. Importing SVG: In this section, we're going to bring in the base map. This is going to be the outlines of the globe that will form a context for understanding where these meteors strikes have happened around the world. One of the items in the data folder is a graphic called WorldMap.svg, and this is an Aqua rectangular projection of the world. You can see our giant Antarctica at the bottom and how the top of the United States, and Siberia, and Canada, and Greenland, have become really distorted. But this will be easy to import and easy to place our markers onto. This came from Wikipedia, you can always search for Aqua rectangular vector map on Google and find other sources. So, what we need to do is make our canvas large enough to hold this map, and use a little bit of code to place it in the background. So, first thing we're going to do is set the size of our canvas to one that matches the proportions of this map. Aqua rectangular map projection is always going to be twice as wide as it is tall. So, if we decide that we want this to be 900 pixels tall, we'll make it 1,800 pixels wide. You set the size of the canvas in processing by with the size function. So, say 1,800 for the width, and 900 for the height. These functions are always begun with an open parenthesis and closed with a closed parenthesis, and at the end of each line you'll need a semicolon. If we hit the play button now, you'll see all of a sudden our sketch is 900 by 1,800 which is much more accommodating. Next thing we'll do is bringing this bit of code to load the baseMap. We're going to need to define our first variable. This is a special type called a PShape, and this is what holds an SVG. So, we define its type first, and then we give it a name. I'm going to call it basemap. You can always see if you're entering code correctly in processing, if you're using these functions, they will they will highlight. So, PShape knows that it's a variable type and it's orange, while these functions know that they're green or blue. In these set up, the code that we're just going to run once, we'll define in these base map. So, we type the name of our variable, and then we need another function, loadshape, which you'll see if I type it all out in lower case it doesn't highlight if I use the uppercase S there, it highlights correctly. Now I just want to give it the name of our SVG, so I'll copy that from the data folder, and I need to put that in quotes here, WorldMap.svg. This isn't quite enough, but let's let's run it just to be sure. Okay, we have a problem with the base map. That's because I didn't put a capital M in the variable name. So, it told me in the console, it cannot find anything named baseMap. Once I've changed the name of the PShape variable, this should run correctly. Now, in the draw mode, I'm going to add one more piece of code and this is what we'll add it to the canvas. This is going to be a function called shape, and I will tell it to put my baseMap at position zero, zero, which is the very first point in the canvas, and that I want it to be as wide and as tall as the canvas. Now, I could either retype the dimensions that I put in the size, or I can use these little convenience methods to just ask the canvas what size it is. These are reserved words like width and height that represent these quantities. So, in this line of code, I'm saying I want a shape that's filled with the baseMap which is our SVG, and it starts at zero zero, and it goes to width and height. I've closed this with a semicolon, and if I run it we've got the map. So, we're in good shape to start bringing in our data and start putting that onto our map. For this class, I've provided you with a properly formatted Aqua rectangular map that I sourced from from Wikipedia. But I've also found there are other places to get maps. This method is only going to work if we use an Aqua rectangular map projection, but you can type this rectangular vector into Google and I'll usually go to the images section to try and find other sources. You can see here, there are many different examples of Aqua rectangular maps with different amounts of detail, or with country dividers on them. So, you can always try putting one of these into your file as well.
8. Drawing Markers: The next step in this is going to be to get some markers drawing onto our map. We'll plug in the data a little bit later, but let's just look at how processing can draw these shapes that we'll need. There are a couple of different types of shapes that processing can provide us with. We can use rectangular, rectangles or ellipses. Let's just start by looking at these two and some of the steps that we'll need to get these to draw in a way that we're excited about. So first function is a rect. You'll see that just by typing rect and putting in our parentheses processing recognizes this piece of code. A rectangle takes four parameters. We want the X and Y location and then the width and the height. So, if I say 100, 100 for the position and I want it to be 200 pixels wide, 100 pixels high, if I run that, you'll see we get this rectangle here. By default, it has a black outline and a white fill. I don't really want it to have this black outline. So, in the line above, I'm going to use this little piece of code, no stroke, and this will turn off the outline if I run it again. So now I just have a white rectangle, but that's pretty invisible. So, what I'll do now is give it a fill. You can do this in several different ways in processing. It will recognize black and white. You can specify it as black and white with alpha, or RGB, or RGB with alpha, alpha meaning transparency. So, first, let's just say I want to fill it with black. The black scale goes from 0 to 100. So if I say fill 0, it will give me a black rectangle. It goes from 0 to 255. So, a value of 255 will give me a white rectangle. If I go back to saying fill it with 0 or black, I can add another parameter which will be a transparency. So here, I can put in 50, and now you can see I have a semi-transparent rectangle. I want to use some color. So, I'm going to go to the color scale which takes three parameters all from 0 to 255. These are in the order of red, green and blue. So if I say 255, 0, 0, I'll get a red rectangle. Now, if I give it one more parameter, like 50, I'll get a semi-transparent red rectangle. We haven't put in the no loop function yet, so this draw loop is just drawing, drawing, drawing constantly. One of the interesting things that you can do in processing is play with color. There's a function called random. This will just set a random value. This can be really useful for experimenting and exploring. In this case, we're saying we want a value between 0 and 255 instead of setting 255. Now you'll see this animation progressing. You can see we've got a flickering shape now and you can drop this random code in wherever you want. But we just want to run this one time. So, to keep this code simpler in our setup, we'll just add a line that says no loop, and this means once it runs once we'll be done. We can test that this is working because now the random will just pick one value and it'll be static afterwards. I'm going to reset this to 255. Let's run it again. We have a red rectangle. Finally, we'll just look at how ellipses are drawn in processing. As you can imagine, this takes a function called ellipse. I'll give it a different position like 500, 500 and a width of 100, and a height of 100, close that parentheses and put a semi colon. Once I run this, I'll get a new ellipse and the next step will be to import some of our data and be able to start drawing these markers programmatically so that they show us where all these meteorite strikes happened around the world.
9. Importing and Parsing Data: For this next section, we're going to bring in the CSV data into a 2D array so that we can process it and place our markers in the right position on the map. Now, we're going to use a bit of repetitive code to parse this CSV into our arrays. I'm going to do a little bit of setup, but this piece of code that we copy over, it's just something that you'll reuse any time you want to import data into processing from a text file. The first thing that we're going to set up is a variable to hold the contents of our text file. This is going to be a string. We're going to call it CSV because that's what it is, and it's going to be an array automatically. This is because when we bring it in, it's going to interpret every one of the returns in that text file as a new line of data. So, the string CSV is going to be a list of all the meteorites. To fill that CSV with the data from the text file, we'll need to have a line in our setup where we define what CSV is. So, CSV is now going to equal the contents of this function which is called loadStrings. This is what you use to bring in data from a text file. So, I've got the function there, and I will just copy in this MeteorStrikes name. Again, this needs to live in quotes. Let's just run this to make sure that everything is working properly. Okay, so the strings are loaded. I'm going to get rid of this rectangle that we had in the previous instance, and I'm going to use the console for the first time. I just want to make sure that everything is accessible, so I'm going to type out this line println. This means print something to the console, and I'll tell it to print CSV, our variable that's holding the contents of our text file. I run this again. There we go, we have 34,000 lines of juicy meteorite data in our console. So, everything's working okay so far. I'm going to delete this. I'm going to setup the 2D array. This is the list of lists where rather than having everything in rows, we're going to now split everything to rows and columns so that we can access any piece of data that we want. In the CSV, we could access a line of data by saying println CSV, and then in one of the brackets, just giving a number like 23 because I know this is an exceedingly long text file. I know that 23 will be in bounds. I'll run this again, you'll just see the 24th line of the text file. What we want to do now is split it up at all these commas, so that I can access any piece of this. To do that, we'll need to define the 2D array that we're going to use. This is going to be a string again. For this one, I'll call myData, and we'll tell it to be a 2D array by having two sets of brackets. So, I've defined that variable. Now, I'm going to explain the processing, how big I want this container to be. I want it to fit the data properly to be efficient, so what I'm going to do is say, "The size of my data is a new string, and I want it to have as many rows as the MeteorStrike.csv file. So, we know this is like 34,000 something, but we can actually get it directly by using this little convenience method of saying csv.length. So, that will just fill it in automatically with the length of the CSV file. I think we have, in here we can count the number of columns that we have, one, two, three, four, five, six. There are six columns, so I specify that as six, and just hit Run to check it again, everything's going all right. The next step will be this bit of reusable code to split up those CSV lines into our 2D array. So, I'm going to copy this from the reference file. Actually, I'll type it out again. We're going to use our first four loop so, I'll just set up the basic skeleton of the for loop that starts with for open paren and close paren, and then an open brace, and a close brace. Now, I'm going to set up the conditions for the for loop. This will be, for an Integer i, that's zero, while it's less than the length of the CSV so csv.length increment it, that's i plus, plus or i equals i plus one. Then what we're going to say is that this 2D array myData for each of the positions i in this container, we want to split that CSV on the string that's character of a comma. So, csv i.split, this is a string function that will tell it the character on which you want to split it, and I've done everything correctly here, and hit Run. It's done that all in the background. Now, let's just print some random bit of myData to make sure that that it's working correctly. So, I'll add another println. I want to access myData at position 23 again, but this time, I want the the fourth row or the fourth column in row 23, close that and run it, and there we go. I have one bit of locational data being spread out. So, I think everything's in the system now where we should be able to cycle through it, and start making our markers. Feel free to copy over this for loop or even the completed setup section. Now that we're done, this splitting on the comma's piece of code is something that I typically just copy from one project to another, and I don't worry about memorizing it.
10. Converting lat/long to Screen Coordinates: So, at this point you've got this CSV imported into processing, and you've copied that code. So, we've got a parsing into a 2D array and now we can step into our draw section, and start to convert it into screen coordinates so that we can place it on our map. Let's go into the draw section, and what we're going to do, is we're going to set up another for loop here to cycle through all of our data. Hopefully, this is getting a bit more familiar to you. Like I said earlier, this is the same structure that we use over and over throughout processing. We'll start by typing for, open and close these parentheses, give it a brace for what we want it to do during the for loop and close that brace. Again, we can use this int i structure. It's not going to conflict with the i we used up above because these are in different contexts. If you want a variable to be accessible throughout the whole project, we have to set it here in the global variable section. So, I'm going to use i again, I'm going to say for int i equals zero, i is less than the length of my data, so that's my data.length. Add one to i, i plus plus. So, I'm going to run this, make sure everything is good. Looks good still. I'm going to move this ellipse that I drew earlier into the for loop. But just leave it like that and I run it, I'm going to get 34,000 ellipses stacked on top of each other. You can see already, that the code has slowed down a bit, but now the red of the ellipse is totally opaque, because all those transparent ellipses on top of each other have now become a solid mass. We're going to hold off on drawing this ellipse. So, let's just give it two forward slashes to comment it out for a minute. Now, what we need to do is compute the latitude and longitude. We can use the map function to do this. First, let's just print out parts of our data set to make sure that we have them in the right places. To do that, I'm going to use the printIn, and what I want to do, is access my data for every row which will be i, and I think that we are going to work with the CSV file here. We're going to use one, two, three, the fourth, and fifth positions, because we're talking to a computer we need to subtract one, because they count from zero. So, that will be three and four. We can do this actually all in one line by putting a plus here, and open quotes, and, just do another plus in there, and a plus and then the other bit of my data. So, what's happening here, is I'm saying, I want a print two variables, and I just want to stick a little bit of text in between to make it legible. This is going to be a space, and a plus, and a space. So, if I run this I should see all of the data come through here. As you can see in the console, I have the latitude and then the longitude separated by a plus. I can make this a comma or a forward slash if I want to. So, I've got the data in a loop where I can access it all now. I'm going to use the map function to convert this all into screen coordinates. So, to do this, I'm going to set up a new variable. So, I'm going to call graphLong. This is going to be a float, because I want to have a lot of precision to it. It's going to be a decimal number rather than a whole number, and the value of it is going to be the output of a map function. I'm also going to need a graph of that. So, I'll set that up as well with a new variable and the output of this map function. So, if you recall from before, a map function is going to take five inputs. We'll first take the number that we want a map, and then the two scales that we're using. So, let's set up. Let's access the piece of data that we want initially. The first one is going to be this myData [i] [3]. So, we can copy that and put it into the first map, and then this data is going to be on the scale of minus 180 to 180. So, first number here minus 180, 180, and we want this to be mapped to the width of our canvas. We know that the canvas starts with zero and goes to a width that can be accessed by just typing the word width. So, we start with zero and then we'll type width. The process for the latitude it's very similar but we need to tweak the values a little bit. For this, we'll use myData [i] [4], and this is going to be on the scale of minus 90 to 90, and for the earth data, and then it will be on the scale of zero to height four for our screen position. Let's alter this printIn a little bit, let's cut it and paste it below these equations, and rather than plugging in myData [i] [3], let's plug in the output of these map functions. So, we can access that by copying over a graphLong and putting it into the print function, and copying graphLat, and putting into the print function. So, now if everything is working correctly, we can expect this for loop to cycle through all the values for latitude and longitude in our CSV and save them into the variables, graphLong and graphLat. Every time it goes to the for loop, it's going to re-initialize the variable and use the next value. So, what we should expect in the console is for this graphLong and graphLat to print out all the screen values that we're going to need. But I've done something wrong. Yes. This is the one step that's missing. Our data is in string formats. So, thinks that everything it's encountering is a word. Unfortunately, we know that it's a number, and we have to put it into a format that this map function can use. It can only work with numbers like integers or floats. So, the way to tell processing to use this myData, that it thinks is a word because it's coming from a set of string variables. We have to cast it to a number. This means just translate it, and the way we do that is with a little function called float. So, if we wrap myData in a float and in the line below, we'll wrap that. In a float this should now be possible by the function, and our console should spit out all the screen values that we'll need. You can see, now these set of numbers is on the scale of our canvas. They should all be in less than 1800 in the first number and less than 900 in the second number. Now, if you've got this code working, you can either copy it from the other file or hopefully tweak it until it's successful for you. Let's get to our ellipse to draw all these markers on screen. So, rather than giving it explicit dimensions like 500 and 500, we can now tell it that we actually just want to put all our dots at graphLong and graphLat and 100-100 it's going to be pretty big, let's make them 10 by 10. If we run this we should see our first glimpse of all this data appearing on the map. We've made a mistake somewhere. As you can see, this map is upside down. These meteorites are not landing on our continents. So, I think what I need to do, I need to change this mapping of scale. Rather than going from minus 90 to 90, I want it to go from 90 to minus 90. Hopefully that change we'll be the right one. There we go. That looks much better. We've got all of the meteorites landing on Earth now, and in the next step we can plug in the scale of the size of the meteorite to the size of the marker that we see on screen.
11. Connecting Markers to Data: Okay. In that last section, hopefully you had the thrill of getting all the meteorite markers onto the map. Now, we're going to do a little bit of math to scale them properly, and access the mass of the Meteorite. We are going to do a little bit of cleanup on this For Loop, get rid of the space here, and I'm pretty happy with the rest of this code. So, I'll leave it in place. What I'm going to want to do, is define a variable for the diameter of each of these meteorites. So, I need to use my correct area calculation, and access the right piece of data from our CSV to plug it into this equation. Again, I'm going to want a float, and let's call this markerSize. This is going to be the container for the diameter of our meteorMarkers. So, let's check again where the scale of our Meteorite is being held. So, it's being held in the third column of our text file. So, we'll access that with the my data 2D array. We can keep using (i) to iterate through all of them, but we use the the second position now. So, now I need to plug the markerSize into the size of the ellipse. So, rather than using a static one, I'll just say paste markerSize where I was saying 10 before. We can try this, but I think that two things. One, these markers are going to be enormous. We won't be able to see our map, and also we have to turn the string that my data is returning into a float. We have to make it something that the ellipse drawing code can recognize. So, now we're saying "Take that word that's defining a number and treat it like a number." You should turn off the println, function now, I think it's going to take too long and slow down this process. So, let's delete that and run this again. So, a bunch of red, that's because some of these markers were 60 million grams. So, we're going to really need to scale down these markers. Unfortunately, one of the things we're going to do, is we're going to implement this area calculation. So, as I showed you in the initial concepts, we need to take a square root of the size of the meteorite and divide it by pi and that will give us the radius. So, let's see. We have a function for doing square root in processing it's SQRT, and maybe it has lowercase. sqrt, open a parenth, and close parenth. So that'll bring down the size of the marker a bunch, we also have to divide it by pi. So, we use a slash and Pi as a convenience method in processing as well just PI, and I'm just going to multiply it by 0.5. Let's see. So, whatever it is, I'm just going to divide it into to scale it down a little bit. Let's try running this again. All right, it's getting a bit more rational, but it's still outside of the bounds of acceptability. So, let's add in another decimal to the scaling factor. So, now multiply it by 0.05, and that looks pretty good. I can make out areas of density, and areas where there aren't that many meteorites. I'm going to even try boosting this a little bit. Say, 0.1, and run it again. I'll leave this scaling up to you. I think I'm going to go back to 0.05. That seemed to show me a good amount of detail here, while also communicating a bunch of the density of these meteorite strikes. So, I don't think there's a right or wrong answer to finding the correct scale here, but we can go to small pretty easily, if we go to 0.01, I think we're just going to start missing this density, a lot of the smaller meteorites are now invisible, whereas if we go to 0.1, I think a lot of these areas just get too crammed up. So, I'm starting to lose detail in the midwest of the United States and I think I want to bring it down a little bit, so that I can see some more of that. So, I'm going to try half of this, 0.05. Which to my eyes seems to balance the right amount of detail in the smaller areas with some of the density that I think communicates the intensity of Mexican meteorite strikes. This is illegibility decision of ensuring that you can you can see the full data set in your visualization.
12. Labeling Markers: Okay, so, we've got all the meteorites drawing onto our map, they're all scaled properly, we've converted our quantities to area with the proper methodology, and now I just want to label some of these. And the keyword here is, some of them, because with 34,000 meteorites on our map, it would really bog down both processing and illustrator to try and label them all. So, I want to label a subset, and if you remember we output the CSV with the largest meteorites on top. So, we can just say,"For the first 20, let's put a label on it, or even the first 10." And we'll know that these are the top 10 meteorites in our selection. So, to do that, we're going to use one more little function here that's an if function, this is basically just going to test some output and see if we should be doing something. This is similar to a forward loop, we'll say if, and open parens close parens, and open bracket close bracket, and I simply just want to say if i is less than 11, that'll give me the, actually if i is less than 10, that should give me the top 10 meteorites sizes, and this is where I'll put the labeling code. So, first I'm going to just want to put the text on the screen. And it's not that hard to add text into processing, predictably we use a function called, Text, that's going to define what we want to put on screen, and we just need to tell it what to write, and where to put it. We already have this information in our system. So the CSV has a name, so and that's in our mydata two D array, and that's in the first position. So, it will be mydata i in position zero, and then the next parameter is just going to be our graphLong, and the next one will be graphLat. Now, I'm going to run this, but it's just going to put the text right on top of our marker, so, we'll probably want to offset it. You can also see that it's drawing it in the same color as the meteorite, so we want to change that. I'm going to want to draw these in black. So, how we do this, is you just need to add another line for the fill, and I'll say fill it with zero. The problem is that, this fill is now inside the four loop, so, I'll get one meteorite drawn in red if I do this, and all the others will be drawn in black. Maybe we'll be able to see this. No, I can't see the red one. But everything's drawn in black now. So what I need to do is move this fill description into the four loop, so every time it starts over, it will set my meteorites to being set with the semitransparent red, and then when it gets to the text section, it will set it to being filled with black. If I run this again, hopefully the results will come through, great. We got black labels on our semitransparent red meteorites. Now I want to move all these labels off of the circles, so that I can use a line to attach them to the correct meteorite strike. We can just do that by specifying some offset, and one of the nice things is we already know the size of each of these circles in this iteration. So, I'm going to say I want to offset it by graphLong plus the marker size, plus 100, see if that's enough. Alright, that's looks like too much, so, maybe I'll just do it by 30, we'll try that out for size. Really micro-size. All right. It seems reasonable. Now let's draw a line that connects the piece of text to the meteorite. I don't want to fill my line with zero, I actually want to give it a stroke, so, I will say, no fill, and I want my stroke to be black. So, this will be stroke of zero. And when I start this loop over again, I don't want to be using that stroke. So, up top I will have to say no stroke. Drawing a line is about as simple as drawing some of these other shapes, we're just going to say I want a line, and this will take two measurements, the starting x and y position, and the ending x and y position. In this case, we know that we want to start it at graphLong plus the marker size, and graphLat. So we're adding the marker size here so that it starts at the edge of the circle, I can take it off for now so that we can see how that will point to the center of the circle if we don't use it. Then, the end point of this is going to be graphLong again, plus the marker size and graphLat. Let's see what this does, and how we need to adjust it. Surely going to. So it's running into our text a little bit, and it's running into the center of the marker. So, I want to get this line to just connect to the very edge of our marker, that way, in some of these denser areas you can see which circle is being described. So to do that, I will add the marker size over two to get that to work. So I need to divide it by two, otherwise it will be the diameter of the circle. That's great, we've got a connecting to the edge now. And I just want to move the text over a bit to the right, and a little bit down, that should make our connection complete. So, the text I will give it a little bit of padding, like five pixels, and the graph latitude, and give it another say five pixels, and you can tweak these values to get it to where think it's comfortably lining up, its looks a little bit low to my eyes, so I'll change that five to a four, and now that's looking pretty good. The line and the text are all connecting to our meteorites, and let's add a little bit of code so that we can get this out as a PDF.
13. Making a PDF: Okay. We're all set. We've got all our circles being drawn at the right scale in processing, we've got text labels that are connected to our markers in a great way. The next step is, how do we get this into a PDF, so that we can bring it into Illustrator, and do a couple of final tweaks to it, or take it further, bring it into InDesign or Photoshop. We're going to need a library to do this, and this comes automatically with processing. You just have to add one little bit of code under libraries. In fact, you can just do it under the sketch menu in processing. If you say import library, there's a PDF right here, and it will plop in the right piece of code. Or you can just copy it from the reference file. We say import, processing.pdf, and now we have access to the tools required to save us a PDF. The rest of the code for this, will go around our draw area. So, all we need to do is say, start recording at the beginning of the draw, and then recording at the end. In the start recording code, we'll just tell it what we want our PDF to be named. So, say begin recording or begin record, and open close brackets, put in that semicolon and we wanted to save this as a PDF so, that's the first parameter, and the second one is just what you want to call it. I'm going to call it meteorStrikes.pdf. Make sure that's in quotation marks, and at the end of our draw loop, we will just say, end record, it's as simple as that function, and I'm just going to add one little console output here, so that I know that the PDF is done saving, and that will just be something that says PDF saved. So, printlin and PDFs saved. This is just a little helpful thing for me to know that I can check, and it's safe to open the PDF. So, it's run. I see in the console, it says PDF saved. I will close this sketch, and if I go to its parent folder, you'll now see that I have a 1.1 megabyte PDF called meteor strikes there. I can open it in preview, and it looks pretty good. I'm going to try opening this in Illustrator now, and see what I need to change if anything, and how I can make this just look a little bit better. I'd love to give it some nicer typefaces than the default one that I get in processing, and I might add a title or change the colors. I've got it open in processing now. There's going to be one little thing that I think I'm going to want to change. By default, processing outlines all the texts when it brings it in. So, if you go to outline mode in Illustrator by pressing Command Y, you can see that this is not live text anymore, it's all been outline. So, if I want to change any aspect of it, I'm going to need to add a couple more lines of code in processing to make it live text. Hopefully, you can see some of the detail that we've got in this PDF, it's just pretty phenomenal, the density that can be created. Here in Saudi Arabia, we've just got a lot of meteorites strikes. What that means, is up for you to decide to explore in more depth. Are they good at finding them there, or do they just tend to get a lot of meteorites? Processing can save things as a PDF or a JPEG with different bits of code, but because we're interested in bringing this into Illustrator and doing a little bit of clean-up on it, we've imported that PDF code and set it to export that way. This is one of the things I really like about processing, is that for a graphic designer steeped in working in print, I want vectors, I don't want JPEGs or PNGs. Now, to get this type to be live, there's a couple more bits that we're going to need to add. We'll need to add a new container that's called a P font. I will just name it F, and this is where the typeface that we define is going to live, and will be able to output live type in our PDF. In our setup, the code that we just run once, I will now define F. This is going to be a function called createFont, and you can use any typeface that's loaded on your machine. I'm going to use Avenir because I think that Mac's get it by default. So, this should work for everyone, and looks a bit better than the default typeface we were using before. So, the way to reference is in this case, by saying then the name of the font and the weight that we want. I want Avenir medium, and I want it to be size 12. So, I should have this typeface setup. Now, I just need to specify that I want to use it in my graphic. I have to use a different text mode so that it won't outline everything. This is this one line called text mode, and the code for the way we want it to be treated, as a model. I think this should do it. One more line above where we specify the text that's being written, we're going to say we want to use this typeface that I've defined. So, just a pretty simple line here, text font F. Hopefully, that will do it. Let's give it a run. So, this is going to re-run the sketch, re-save the PDF over our old one, and then we'll bring it into Illustrator and make sure that everything's working properly. I can see my sketch now, that the Avenir typeface is being used. So, things look a little bit more designy, and I'm going to open this PDF that it's given me in illustrator. Then go to preview mode again. I can see now that the type is filled, and if I switch to the text tool, I can select it and I can change things. So, that's looking good. Okay. Now we've got everything in Illustrator, our text is editable, and we can go ahead and play around with tweaking some of the type, eliminating some issues that might be appearing in our sketch and tweaking some of the colors.
14. Cleaning Up: All right. We're here in Illustrator now. We've got this nice PDF that we've saved out with all of our meteorite strikes. We've got a bunch of labels. Looking at it now, I think we could probably add a couple more. So, if you want to just go to Processing, you can change that number of labels from 10 here to 20. I think we'll get something that has a little bit more richness to it that will just pop back into Illustrator. Yes. Great. So, reopen our PDF in Illustrator. So, I've got 20 labels on this map. First thing you might notice in Illustrator when you're looking at this PDF is, if you click on this graphic, you just get the bounds of this outer rectangle, and one of the things that Processing does is it puts a map mask over the entire output. So, the first thing I do whenever I go into Illustrator is I just need to remove this mask. So, under Clipping Mask, under Object, I'm just going to say release the mask, and now if I select my bounds again and delete it. Let's see. It looks like I've released one mask, but that was just on the map. Now, I'm just going to select all and, again, say Clipping Mask, Release. So, this should allow me to select anything now. Yeah, I've got my text. I've got my labels. So, by selecting all and under the Object menu saying clipping mask release, I'm able to access all the various pieces of this map that I want to get to. So, everything is conveniently a different color now in Illustrator, and I find this really useful because now we can group things back together. We've got our background in a gray color. We've got the map that's in white but it's fragmented. So, let's select one piece of the map, and under the Select menu, we'll just say select the same fill in color. Now, we'll group these by hitting Command G. So, I've got my background, it's accessible. The map is accessible. I'm going to do the same process for the meteorites, the labels, and the lines. So, I'll select one meteorite. Say Select, Same, Fill and Stroke, and I'll grab them all, and I can group them. I'll grab a piece of text. Select, Same, Fill and Stroke, group them and grab the lines and do the same thing. Great. So now, my five different components are all really easily selectable and editable. Next thing you might notice is that this file is an RGB. This is going to be fine if you're heading to screen output, but I generally think about colors more in a CMYK or a print sent. So, I'm going to just change everything to CMYK right now to make things a little bit simpler. You can see that immediately there's a little bit of a color shift from the RGB red to a CMYK red. But I actually don't even want these meteorites to be a red color. I'd rather make them something that's more along the lines of my aesthetic. I like a bluegreen. So, I'm going to go for cyan, say 80 and add in 30 yellow and there we go. We're in a nicer place. We could even edit the transparency if we wanted to. If we weren't satisfied with what Processing had given us. If you go to Window, Transparency in Illustrator, you'll see that at the moment, everything is set at 100. That's for the entire group. If we ungroup it, then we'll gain access to the individual components, and they're all set at 20 percent opacity. So, maybe I'll change that to 30. You could even look at it at 100 percent opacity, but I think what you'll find is that a lot of the detail that we were enjoying before disappears now. We get this solid map where you can't see some of the underlying aspects. So, probably, anything under 50 percent is best for this task. Yeah, 50 is a little dark for my taste. I'm going to step it down and I'll group these back into one big selection now. The text is now in Avenir. I can see it's actually falling a little bit behind some of these meteor strikes. If you zoom in here, you'll see that some of them are falling on top. So, I want to move that selection to the foreground. Let's see, Object Arrange, Bring to Front. Okay. So now, our text is on front. I've also got a couple of collisions happening in the text, so I'm going to both want to change the typeface to something that I like a bit more than Avenir and I'm going to want to move around some of the labels that are starting to collide with each other. So, first, let's select this type group. I've been a fan of this new typeface called Input recently. It's a free typeface offered by Font Bureau. It's really good for text editing and has an informational bent to it that I like. As these narrow weights that also work better in data visualization because you can get more height out of your typefaces when they're a bit more compressed. So, I'm going to switch this to Input Sans Compressed, in the regular weight. It's a pretty black black right now. If you look at the CMYK, it's pretty heavy. So, that's from the conversion from RGB, so I'm just going to set it to 100 percent K or 100 percent black without any of the other CM and Y components to it. That's looking good. These lines are a little bit thick as well and are set to this really, really rich black that's too dense for our needs, so set that to a proper black and change the stroke from 1.2 to half a point, and I'll give it a little bit more lightness and it won't be so distracting from some of the information that we're trying to represent here.
15. Typography: The last problem that I have here are, two places where these labels are colliding with each other. So, what I'm going to want to do is just flip this whole thing over. Because all these lines are grouped, I'm going to have to go to the open arrow selector, the group selection tool, that'll let me grab one of these lines, also see that these lines are sitting behind the meteorites. So, I want to do the same thing I did with the text, and bring this whole group all the way to the front. So, I'll do that with the object, arrange and bring to front. So, going back to the group selection tool, I'm going to grab this one line, and by holding shift, I'm going to grab a piece of type, and I'm going to scoot that over to the right edge of the meteorite that I'm dealing with. Then I just need to change the orientation of this piece of type from left aligned to right aligned with the paragraph tool, and scoot it over to the edge of the line. One of the nice things about processing is that it's measurements stay the same when you come into Illustrator. So, while it's dealing with pixels in our measurements there, they actually they translate to points in Illustrator. So, I think the distance that I had for the offset from the line to the type was five points, and you can see that if I move over one of the labels to the lines, its offset is five. So, if I just scoop my label, five points to the left, it'll be In exactly the correct position as all the other ones, and I'm just going to move over this one other label here. Actually I have, looks like I've go two to move here. They're all colliding with each other. Using the group selection tool, I'll pick this piece of text, and the line associated with it, and move it to the right edge of the the meteor. It's this outermost one, let's see if we've got it right, because the line will connect to the leftmost edge of the circle and change the text to right align, move it to the edge of the line, and then scoot it over five pixels, 1-2-3-4-5. Now we can see that our options for adjusting a labeling have run out of left and right iterations, so we'll need one more little tweak to this to get it to work properly for the Morito meteorite strike. So, if I grab that line and the label, I'm going to move it down. It has to go along with this smaller circle in here. So I'm just going to add one more iteration to our labeling options, where I rotate this line and put the label right next to it. So, this goes here, and the Morito label can either go next to it, or below it. I think I'll change it to center aligned and scoot it five pixels below that line. I think that has cleaned up all of our output from processing, and the last thing I want to do is just give my graphic a title. I think one of the most impressive things about this dataset is the sheer size of it. So, this is a good place to call it out, to talk about the entire breadth of this graphic, and that is that it contains 34,000 meteorite strikes. So, I'm just gonna go right back to where we started this original data set to get an accurate count of how many we represented. I can see it has 34,066 rows, meaning there's 34,065 meteorites represented, and I'll just need a new piece of type to lay that out, 34,065 meteorite strikes. I'll put this in a corner where there isn't much that it's going to obscure, and give it a larger size, so that it's immediately apparent and hopefully will draw you into this very detailed map of the globe. 40 points should do it. Yeah. Give it a little padding, and I think we're in good shape. You can now save this as an Illustrator file, you can bring it into Photoshop, you can export it as a PDF, or a PNG, or a jpeg, and post it wherever you want, and hopefully share the final output on the Skillshare page.
16. Conclusion: So, in this example, I think it would be hard to go wrong with the color. You want something that's certainly going to have visibility, but we're only coding for one type of event here. Probably using yellow is not going to have enough contrast or impact and we want to stay away from using grays because we're using that to define the base map. So, I think something that's bright and works well with transparency, so it builds up to something solid and impactful is good. Then when we're using type, you have to think about the scale that this is going to be seen at and how distracting it's going to be from the information you really want to communicate. The heart and soul of this page is all the meteorite strikes. So, if the type is too large or too fussy, it's really going to overpower the data that we're trying to express. So, I like to use something that has an even texture, that can be condensed because this can give us a lot more impact in a small amount of space. Yeah, and generally stick with aiming for legibility. So, unless I'm coding for something so probably just be black text. If I'm trying to express what a label or a key, then I might change the colors. This is an approach that's really true to the data. If you look at that spreadsheet and you look at this map, I think we've certainly represented most of the information shown there. We've got the latitude and longitude of every single one of those meteorite strikes and we're also representing their relative scales. In addition, we've even labeled some of them and you can go further and you could code these by found or fell. This is something that you really have to pair back the aesthetic in order to be able to communicate this density of information, which is why there aren't really any decorative elements here. I think I would just be distracting from the core of what we're trying to communicate here. Which is something someone could spend a lot of time with analyzing the nuances of where these events happen. I think this dataset is really compelling to explore as a map because you see these really large events, some of them near where we live, others that might be really, really distant and I think what's interesting here is it also becomes somewhat of a map for population density. It does start to show where people live. If you look at Siberia or you look at the rainforest, you don't see any meteorite striking there. But, I think it's probably apparent that this is not because they don't happen there, it's just because they haven't been recovered or they haven't been seen there. So, this for me it's almost like it's a taste of what's actually happening. We have 34,000 known meteorite strikes, but think about all the ones that happen in the ocean or happen in Siberia that we just don't even know about. That's what's quite compelling for me about seeing this map.