{"componentChunkName":"component---src-templates-chapter-js","path":"/module1","result":{"data":{"site":{"siteMetadata":{"courseId":"amgeo_ec_workshops_py"}},"markdownRemark":{"htmlAst":{"type":"root","children":[{"type":"element","tagName":"exercise","properties":{"id":"1","title":"Why Python?"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"You might be wondering why you should be learning Python."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Python is widely used in the scientific community and it is a great tool to help you further advance your geosciences research."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We will present you with the most important reasons to start using Python in the following "},{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/foundations/why-python.html"},"children":[{"type":"text","value":"link"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"2","title":"Getting Started with Python"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Now that you know why you should be learning Python, let’s get started!"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Read the "},{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/foundations/quickstart.html"},"children":[{"type":"text","value":"Quickstart zero to Python"}]},{"type":"text","value":" article and try to run the code using Binder."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"Tip"}]},{"type":"text","value":": Make sure you open the Binder link under the “Rocket Ship” in another window. This may take a while to build so you may want to have it run in the background while you read the article)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"But what exactly is Binder? Binder allows you to run code in a pre-defined environment without installing anything on your computer. The environment is installed on the Binder servers. One of the features of Binder is that it has no memory. So once you close your Binder session, none of the variables or files you download on the server will be there. Remember this as you work through the exercises. Each block of code launches a different Binder. Therefore, if you create a variable in Exercise 3, it’s not available in Exercise 4 unless you create it again."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Once you are done with the tutorials, complete the exercises below to test your understanding!"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Be patient - it might take a few minutes the first time you run the code. But it usually speeds up."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Question:"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Print “I love doing paleoclimate research with Python” on the console."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"01_01"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Remember to use the print command!"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"3","title":"Playing with lists"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Question:"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Lists are one of the basic elements in Python and allows you to build more sophisticated objects. It is common to rely on this data structure for some of its functionalities. Lists are also a great way to loop through information."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a list with the following archives: "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Marine Sediment"}]},{"type":"text","value":", "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Coral"}]},{"type":"text","value":", "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Ice"}]},{"type":"text","value":", "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Wood"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Loop over the list to print: “I study paleoclimate using ” [archive]"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"01_02"},"children":[{"type":"text","value":"\nRemember that lists are defined between `[]`\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Lists can have any kind of elements in it - "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"strings"}]},{"type":"text","value":" included."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"You can concatenate strings using "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"+"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"For example,"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"str1 = \"I love Python\"\nstr2 = \" and I can't wait to use it in paleoclimate research\"\n\nstr = str1 + str2"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"str is now “I love Python and I can’t wait to use it in paleoclimate research”"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"4","title":"Playing with dictionaries"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"A dictionary is a map between key-value pairs."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"For example:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"A location has a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"latitude"}]},{"type":"text","value":" and a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"longitude"}]},{"type":"text","value":".\n"},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"latitude"}]},{"type":"text","value":" and "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"longitude"}]},{"type":"text","value":" are the keys and the coordinate numbers are the values."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"How does this look in terms of a data structure?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"python"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-python"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-python"]},"children":[{"type":"text","value":"location "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"="}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"{"}]},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'latitude'"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","number"]},"children":[{"type":"text","value":"49.26"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":","}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","string"]},"children":[{"type":"text","value":"'longitude'"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":":"}]},{"type":"text","value":" "},{"type":"element","tagName":"span","properties":{"className":["token","operator"]},"children":[{"type":"text","value":"-"}]},{"type":"element","tagName":"span","properties":{"className":["token","number"]},"children":[{"type":"text","value":"123.24"}]},{"type":"element","tagName":"span","properties":{"className":["token","punctuation"]},"children":[{"type":"text","value":"}"}]}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Question:"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a dictionary called "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"dataset1"}]},{"type":"text","value":", that have the following keys: "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"archiveType"}]},{"type":"text","value":", "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"geo"}]},{"type":"text","value":", "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"data"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Set the value for archiveType to "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"marinesediment"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Set the value for "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"geo"}]},{"type":"text","value":" to another dictionary with keys "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"lat"}]},{"type":"text","value":" and "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"lon"}]},{"type":"text","value":". The "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"lat"}]},{"type":"text","value":" value is "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"-5"}]},{"type":"text","value":" and the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"lon"}]},{"type":"text","value":" value is "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"140"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Set the value for "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"data"}]},{"type":"text","value":" to a dictionary with keys "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"values"}]},{"type":"text","value":" (set to a list of "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"[1,2,3]"}]},{"type":"text","value":") and "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"units"}]},{"type":"text","value":" (set to "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"N/A"}]},{"type":"text","value":")"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Return the value of the latitude information into a new variable called "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"latitude"}]}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"01_03"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"When using nested dictionaries, you can access the value in the nested dictionary by chaining the keys."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"What happens if you don’t know which keys are available to you? You can print it out as follows:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"01_04"},"children":[{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"5","title":"Introduction to Basic NumPy"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"NumPy is the fundamental package for scientific computing in Python.   \nIt is a Python library that provides a multidimensional array object,  \nvarious derived objects (such as masked arrays and matrices), and an  \nassortment of routines for fast operations on arrays, including \nmathematical, logical, shape manipulation, sorting, selecting, I/O,  \ndiscrete Fourier transforms, basic linear algebra, basic statistical  \noperations, random simulation, and much more. \n- NumPy Documentation"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"This section contains Project Pythia’s tutorials on array computing with NumPy."},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\nWe recommend using the provided Binder link to run the code."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/core/numpy/numpy-basics.html"},"children":[{"type":"text","value":"NumPy Basics"}]},{"type":"element","tagName":"br","properties":{},"children":[]},{"type":"text","value":"\n"},{"type":"element","tagName":"a","properties":{"href":"https://mybinder.org/v2/gh/ProjectPythia/pythia-foundations/main?urlpath=lab/tree/core/numpy/numpy-basics.ipynb"},"children":[{"type":"text","value":"NumPy Basics Binder"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Question:"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a NumPy array that starts at 0, ends at 1000, with 1001 points and save it into a variable called "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"time"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"What is the value of time at index 20? Return this value into the variable "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"time_index"}]}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"01_05"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"1-D NumPy arrays can be indexed the same way as lists."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"If you are new to programming, your first question might be: “What is an array?“. An array is a collection of values (numbers, strings, or such), whose position in the computer’s memory is such that it can be computed from its given key. Coming from the Excel world, you could regard a spreadsheet as a 2D array; a single column of that spreadsheet would be a 1D array. Arrays, however, are far more general, and can assume any dimension, which makes them great for storing large quantities of information."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Question:"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"It is often useful to create pseudo-data to test out a function. For instance, it could be useful to pass a timeseries with known periodicities to look at the effect of noise or uneven sampling on the different methods. In this case, you may need to create a time and value axis that would mimic a time series."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Let’s start by creating a perfect series:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a time vector that starts at year 1, ends at year 2000 and is annually resolved. Use "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"numpy.arange"}]},{"type":"text","value":" to do so"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a sinusoidal signal corresponding to the time vector with a periodicity of 20 years."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"03_01"},"children":[{"type":"text","value":"\nTo create a sine wave, look whether numpy has a functionality to do so in [their documentation](https://numpy.org/doc/stable/index.html).\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The mathematical formula is: sin(2 pi * freq * time)"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Question:"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Let’s add noise to our series."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a time vector that starts at year 1, ends at year 2000 and is annually resolved. Use "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"numpy.arange"}]},{"type":"text","value":" to do so"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a perfect sinusoidal signal corresponding to the time vector with a periodicity of 20 years."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Use "},{"type":"element","tagName":"a","properties":{"href":"https://numpy.org/doc/stable/reference/random/generated/numpy.random.Generator.normal.html"},"children":[{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"numpy.random.Generator.normal"}]}]},{"type":"text","value":" to create a white noise that samples from a normal distribution with zero mean and half the variance in the signal."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Add the noise vector to your signal"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Look at the first line after package import. This allows you to use the same seed for the random number generator, which makes your results reproducible."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"03_02"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Remember that the variance is the square of the standard deviation."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"So the scale will be "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"np.sqrt(np.var(value)/2)"}]}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"6","title":"Intermediate NumPy"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Now that you have the basics if NumPy, let’s move on to more advanced functionalities. Review the article below from Project Pythia and use the associated Binder for training exercises."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/core/numpy/intermediate-numpy.html"},"children":[{"type":"text","value":"Intermediate NumPy"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://mybinder.org/v2/gh/ProjectPythia/pythia-foundations/main?urlpath=lab/tree/core/numpy/intermediate-numpy.ipynb"},"children":[{"type":"text","value":"Intermediate NumPy Binder"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Question:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"One of the most routine manipulations of paleoclimatology is to take a timeslice of the data. Let’s do this using NumPy."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a time vector that starts at year 1, ends at year 2000 and is annually resolved. Use "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"numpy.arange"}]},{"type":"text","value":" to do so"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a perfect sinusoidal signal corresponding to the time vector with a periodicity of 20 years."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Slice the value data for the 200-400 year period, inclusive"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"03_03"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"To get the indexes of the slice, you can use "},{"type":"element","tagName":"a","properties":{"href":"https://numpy.org/doc/stable/reference/generated/numpy.where.html"},"children":[{"type":"text","value":"this function"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Remember that slice notation is "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"exclusive"}]},{"type":"text","value":" of the final index."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Question:"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Another task we love to perform is wrangling age models. You can think of each age model being stored along one dimension of a NumPy array. Therefore, it is possible to wrangle them the same way you would any other array. Let’s build a fake age model, add some noise to create an ensemble and take the mean (in reality, you may only need to perform the last operation but it’s good practice to play with the random generator you used in exercise 1)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a time vector between 0 and 10000 in 100 years increments"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Use a seed of 30 to initialize the random generator"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Duplicate the time vector to obtain 1000 copies. The resulting array should have each model stored in the column. The rows should correspond to ‘depth’"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a noise vector with standard deviation 200 years"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Add the noise vector to the original ensemble"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Take the mean"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"03_04"},"children":[{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"7","title":"Introduction to Pandas"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Pandas is a very powerful library for working with tabular data (i.e. anything you might put in a spreadsheet – a common data type in the geosciences). It allows us to use labels for our data so that we can write expressive and robust code to manipulate the data."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Key features of Pandas are the ability to read in tabular data, slice and dice data, and exploratory analysis tools native to the library."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Follow this Project Pythia tutorial on Pandas."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/core/pandas/pandas.html"},"children":[{"type":"text","value":"Introduction to Pandas"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://mybinder.org/v2/gh/ProjectPythia/pythia-foundations/main?urlpath=lab/tree/core/pandas/pandas.ipynb"},"children":[{"type":"text","value":"Introduction to Pandas Binder"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In the materials above, you have seen how to download a dataset and open it with Pandas. You can also pass the dataset directly into the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"read_csv"}]},{"type":"text","value":" functionality. Try the code below:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"04_01"},"children":[{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Question:"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Open the ENSO dataset (you may copy and paste the answer from above)"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Create a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Pandas.Series"}]},{"type":"text","value":" object using the Nino12 Series"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Slice for the 1982-2010 period"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Plot the timeseries for the sliced Nino12 series"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"04_02"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Remember that they are more than one way to skin a cat with Pandas. Choose the slicing method that is the most convenient (index, label)"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"8","title":"Introduction to Matplotlib"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"Matplotlib is a comprehensive library for creating static, animated, and \ninteractive visualizations in Python.\n- Matplotlib documentation"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Matplotlib is the go-to library for plotting within Python, with many functionalities and names reminiscent of Matlab’s plotting libraries. Matplotlib comes with very good default parameters, so you can get visualizing within a few minutes of installing it. It is also extensively customizable, and can be used to make publication-quality graphics."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"if you were to learn a single plotting tool to keep in your toolbox, this is the package."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The key feature to Matplotlib is its extensibility and the extensive "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org"},"children":[{"type":"text","value":"documentation"}]},{"type":"text","value":" available to the community. Matplotlib underlies many other graphics libraries, including Cartopy (next chapter), and Pyleoclim, so it is essential that you understand a bit about it."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"As before, we recommend looking over the "},{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/core/matplotlib/matplotlib-basics.html"},"children":[{"type":"text","value":"Pythia Matplotlib tutorial"}]},{"type":"text","value":" first. "}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We recommend that you use the provided "},{"type":"element","tagName":"a","properties":{"href":"https://mybinder.org/v2/gh/ProjectPythia/pythia-foundations/main?urlpath=lab/tree/core/matplotlib/matplotlib-basics.ipynb"},"children":[{"type":"text","value":"Binder link"}]},{"type":"text","value":" to follow along the article."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"A First Plot"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We start by loading and plotting the "},{"type":"element","tagName":"a","properties":{"href":"https://climatedataguide.ucar.edu/climate-data/nino-sst-indices-nino-12-3-34-4-oni-and-tni"},"children":[{"type":"text","value":"NINO3 sea-surface temperature"}]},{"type":"text","value":" data. Notice that the code uses pandas (see Chapter 4) to load it; your job is to plot NINO3 vs time and annotate the plot by giving it appropriate labels (with units) and title."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"05_01"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Look up the documentation at "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/index.html!"},"children":[{"type":"text","value":"https://matplotlib.org/stable/index.html!"}]}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Notice that this call to the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"subplots"}]},{"type":"text","value":" method created:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"a "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/api/figure_api.html?highlight=figure#module-matplotlib.figure"},"children":[{"type":"text","value":"figure"}]},{"type":"text","value":" object "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"fig"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"an "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/api/axes_api.html?highlight=axes#module-matplotlib.axes"},"children":[{"type":"text","value":"axes"}]},{"type":"text","value":" object "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"ax"}]},{"type":"text","value":", to which the plot method is applied.  "}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"For such a simple chart, the distinction is immaterial, but it will soon be important to distinguish between figure and axes, particularly when we create figures with multiple subplots."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"If you wanted to change the size of the figure to 10 by 6 inches, say, you would replace the first line of the figure by:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"fig, ax = plt.subplots(figsize=(10, 6))"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We now explore Matplotlib’s infinite customizability. All default parameters are stored in a dictionary called "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"rcParams"}]},{"type":"text","value":".\nrc stands for “runtime configuration” and any changes to "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"plt.rcParams"}]},{"type":"text","value":" will stay for all subsequent plots in your session. These parameters can be customised and "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/tutorials/introductory/customizing.html#customizing-with-matplotlibrc-files"},"children":[{"type":"text","value":"saved for later use"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"For instance, the default figure size can be found as:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"plt.rcParams['figure.figsize']"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Typing this in your Binder should return "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"[6.0, 4.0]"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Let us now customize our plot. First, we might want to remove "},{"type":"element","tagName":"a","properties":{"href":"https://www.darkhorseanalytics.com/blog/data-looks-better-naked"},"children":[{"type":"text","value":"chart junk"}]},{"type":"text","value":" (visual elements that clutter the display without bringing any data-related information to the table. The top and right spines of the chart, for instance, are totally useless, so let’s remove them."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"You can see how to do so "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/api/spines_api.html?highlight=spines#matplotlib.spines.Spines"},"children":[{"type":"text","value":"here"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Apply this to the code from the previous block and see the result:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"05_02"},"children":[{"type":"text","value":"\nhttps://stackoverflow.com/questions/925024/how-can-i-remove-the-top-and-right-axis-in-matplotlib\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"If you want to make this a general feature of all your plots, it is more convenient to set this property as part of the rcParams, like so:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"plt.rcParams['axes.spines.right'] = False\nplt.rcParams['axes.spines.top'] = False"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In a Jupyter notebook or another iPython session (e.g. in Spyder), those spines would then be removed from all subsequent plots."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"9","title":"Intermediate Matplotlib"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"Making and customizing compound figures"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In many instances, figures are composed of several subplots. Here you learn how to make and customize such plots in Matplotlib. First, let’s add another panel to plot the second series, All India Rainfall, and label everything so someone might actually be able to interpret these plots."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"fig, ax = plt.subplots(2,1,figsize=(10, 6),sharex = True)\nax[0].plot(t,nino3)\nax[0].set_ylabel('NINO3 SST (K)')\nax[0].set_title('NINO3 and All India Rainfall')\nax[1].plot(t,air)\nax[1].set_ylabel('AIR (mm/month)')\nax[1].set_xlabel('Year AD')"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Notice that we used "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"sharex = True"}]},{"type":"text","value":" to tell the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"figure"}]},{"type":"text","value":" command that the two subplots had a common x axis, to remove some redundancy. If you’re curious, try removing that and see what it does."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Now we want to customize the appearance of the plot a bit more:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"look up the "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/gallery/text_labels_and_annotations/text_fontdict.html#sphx-glr-gallery-text-labels-and-annotations-text-fontdict-py"},"children":[{"type":"text","value":"documentation"}]},{"type":"text","value":" to see how to make the font bold and set its size to 18."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"change the font of the y-axes labels to ‘Helvetica’."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"05_03"},"children":[{"type":"text","value":"\nLook up the documentation at https://matplotlib.org/stable/index.html!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"A plot with two y axes"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Let’s preface this exercise by saying that including multiple axes on the same graph is "},{"type":"element","tagName":"a","properties":{"href":"https://www.callingbullshit.org/tools/tools_misleading_axes.html"},"children":[{"type":"text","value":"one of the surest ways to lie with data"}]},{"type":"text","value":". However, when done responsibly, it can save space and allow to compare comparable timeseries.  Here’s how to do it for those series:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"#plot"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-#plot"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-#plot"]},"children":[{"type":"text","value":"fig, ax = plt.subplots(figsize=(10, 6))\nax.plot(t,nino3,label='NINO3',color='C0')\nax.set_ylabel('NINO3 SST (K)')\nax.set_title('NINO3 and All India Rainfall',fontweight='bold')\nax.legend()\n# twin object for two different y-axis on the sample plot\nax2=ax.twinx()\nax2.plot(t,air,label='AIR',color='C1')\nax2.set_xlabel('Year AD')\nax2.legend()"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Type "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"?plt.plot"}]},{"type":"text","value":" or search StackOverflow to figure out how to repeat the figure above but change the line colors to red and green and adjust the transparency of the top curve to 0.6 so both are clearly visible."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"05_04"},"children":[{"type":"text","value":"\nLook up the documentation at https://matplotlib.org/stable/index.html!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"Using Style Sheets"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Making publication-quality plots can involve quite a bit of customization, which gets tedious after a while. Thankfully, Matplotlib has implemented a number of "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/3.5.1/gallery/style_sheets/style_sheets_reference.html"},"children":[{"type":"text","value":"styles"}]},{"type":"text","value":", which are predefined dictionaries of plotting parameters governing just about every imaginable aspect of plots. Here we demonstrate how to apply these pre-defined styles to the previous plot. There are two main ways to do so:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Setting a style for a whole kernel/session, which will affect the graphical style of all subsequent plots."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Setting a style as context for a particular plot, not affecting the graphical style of all subsequent plots in your notebook."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"First, we create a "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"function"}]},{"type":"text","value":" to avoid repeating too many lines of code:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"def nino3_air_plot(plot_title):\n    fig, ax = plt.subplots()\n    ax.plot(t,nino3,label='NINO3',color='C0')\n    ax.set_ylabel('NINO3 SST (K)')\n    ax.set_title(plot_title)\n    ax.legend()\n    # twin object for two different y-axis on the sample plot\n    ax2=ax.twinx()\n    ax2.plot(t,air,label='AIR',color='C1')\n    ax2.set_xlabel('Year AD')\n    ax2.legend()"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The function produces that double y-axis plot with NINO3 and AIR with all the relevant information (variable names, units) but no customization. Use code below to loop through available styles and illustrate them on this particular plot:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"05_05"},"children":[{"type":"text","value":"\nhttps://www.dunderdata.com/blog/view-all-available-matplotlib-styles\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"Visualizing Relationships"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"So far we have only played with line plots, but if the goal is to compare two series, one might also explore a "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/3.5.1/api/_as_gen/matplotlib.pyplot.scatter.html?highlight=scatter#matplotlib.pyplot.scatter"},"children":[{"type":"text","value":"scatterplot"}]},{"type":"text","value":". Let’s do this below, using the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"ggplot"}]},{"type":"text","value":" style."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Edit the code block to produce a scatterplot with AIR on the y axis and NINO3 on the x axis. In order to see overlapping points, give each one an opacity of 30%."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"05_06"},"children":[{"type":"text","value":"\nThe parameter regulating transparency/opacity is called alpha, and this is how you use it: https://www.adamsmith.haus/python/answers/how-to-change-the-transparency-of-lines-in-matplotlib-in-python.\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"Adding color as an extra dimension"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"The plot is interpretable, but we have lost an opportunity for insight by giving each dot the same color. Wouldn’t it be nice if each dot’s color reflected the time it represents? Luckily we can do this very simply by specifying "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"c = t"}]},{"type":"text","value":" in the call to "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"scatter"}]},{"type":"text","value":". The colormap argument is "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"cmap"}]},{"type":"text","value":", and you can pick any "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/tutorials/colors/colormaps.html"},"children":[{"type":"text","value":"colormap"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Repurpose the code above to do this with:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"a 12 by 8 in size"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://python-graph-gallery.com/104-seaborn-themes"},"children":[{"type":"text","value":"seaborn-whitegrid"}]},{"type":"text","value":" plot style"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"scatter plot circles with 70% opacity colored by year, using a viridis colormap."}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"05_07"},"children":[{"type":"text","value":"\nhttps://stackoverflow.com/questions/17682216/scatter-plot-and-color-mapping-in-python\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"10","title":"Introduction to Cartopy"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"div","properties":{"className":["gatsby-highlight"],"dataLanguage":"text"},"children":[{"type":"element","tagName":"pre","properties":{"className":["language-text"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-text"]},"children":[{"type":"text","value":"Cartopy is a Python package designed for geospatial data processing in order\nto produce maps and other geospatial data analyses.\n\nCartopy makes use of the powerful PROJ.4, NumPy and Shapely libraries and\nincludes a programmatic interface built on top of Matplotlib for the creation of\npublication quality maps.\n\nKey features of Cartopy are its object-oriented projection definitions, and its\nability to transform points, lines, vectors, polygons and images between those\nprojections.\n- Cartopy documentation"}]}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Before doing the tutorials, make sure that you already have a basic familiarity with Matplotlib."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Cartopy’s cartographic features library includes shapefiles directly served by Natural Earth. It sometimes takes a minute for the code to access those databases behind the scenes, so be prepared for that."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"This tutorial will lead you through some basics of creating maps with specified projections with Cartopy, and adding geographic features like coastlines, borders, topography, and landmarks. We will cover:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"ol","properties":{},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Basic concepts: map projections and "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"GeoAxes"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Explore some of Cartopy’s map projections"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"li","properties":{},"children":[{"type":"text","value":"Mapping a record’s site"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Before we dive in, please look at:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/core/cartopy/cartopy.html"},"children":[{"type":"text","value":"Introduction to Cartopy"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"a","properties":{"href":"https://mybinder.org/v2/gh/ProjectPythia/pythia-foundations/main?urlpath=lab/tree/core/cartopy/cartopy.ipynb"},"children":[{"type":"text","value":"Introduction to Cartopy Binder"}]}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"A basic map"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Recall that in Matplotlib, what we might traditionally term a "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"figure"}]},{"type":"text","value":" consists of two key components: a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"figure"}]},{"type":"text","value":" object and an associated "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"axes"}]},{"type":"text","value":" object."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"By importing Cartopy, we can convert the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"axes"}]},{"type":"text","value":" into a "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"GeoAxes"}]},{"type":"text","value":" by specifying a projection that we have imported from "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"Cartopy’s Coordinate Reference System"}]},{"type":"text","value":" class as "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"ccrs"}]},{"type":"text","value":". This will effectively "},{"type":"element","tagName":"a","properties":{"href":"https://www.usgs.gov/faqs/what-does-georeferenced-mean"},"children":[{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"georeference"}]}]},{"type":"text","value":" the subplot."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Here we’ll create a GeoAxes that uses the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"PlateCarree"}]},{"type":"text","value":" projection (basically a global lat-lon map projection, which translates from French to “flat square” in English, where each point is equally spaced in terms of degrees)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_01"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Although the figure seems empty, it has in fact been georeferenced, using one of Cartopy’s map projections that is provided by Cartopy’s "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"crs"}]},{"type":"text","value":" (coordinate reference system) class. We can now add in cartographic features, in the form of "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"shapefiles"}]},{"type":"text","value":", to our subplot. One of them is "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"coastlines"}]},{"type":"text","value":", which is a callable "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"GeoAxes"}]},{"type":"text","value":" method that can be plotted directly on our subplot."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_02"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Cartopy provides other cartographic features via its "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"features"}]},{"type":"text","value":" class, which are imported as "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"cfeature"}]},{"type":"text","value":". These are also shapefiles, downloaded on initial request from "},{"type":"element","tagName":"a","properties":{"href":"https://www.naturalearthdata.com/"},"children":[{"type":"text","value":"https://www.naturalearthdata.com/"}]},{"type":"text","value":". Once downloaded, they “live” in your "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"~/.local/share/cartopy"}]},{"type":"text","value":" directory (note the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"~"}]},{"type":"text","value":" represents your "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"home"}]},{"type":"text","value":" directory). We add them to our subplot via the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"add_feature"}]},{"type":"text","value":" method. We can define attributes for them in a manner similar to Matplotlib’s "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"plot"}]},{"type":"text","value":" method. A list of the various Natural Earth shapefiles appears in "},{"type":"element","tagName":"a","properties":{"href":"https://scitools.org.uk/cartopy/docs/latest/matplotlib/feature_interface.html"},"children":[{"type":"text","value":"https://scitools.org.uk/cartopy/docs/latest/matplotlib/feature_interface.html"}]},{"type":"text","value":" ."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_03"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Finally, we can add topography as a “stock image”. Notice how cartopy has the good taste to plot it "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"under"}]},{"type":"text","value":" administrative boundaries, so the latter are visible:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_04"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Pretty, isn’t it? You are now ready to explore the dizzying world of projections."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"Projections"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"As you probably know, it is impossible to represent a 3-dimensional object like Earth on a 2D surface (a map) without tear or deformation (try it with an "},{"type":"element","tagName":"a","properties":{"href":"https://rabernat.github.io/research_computing_2018/maps-with-cartopy.html#The-major-problem-with-map-projections"},"children":[{"type":"text","value":"orange"}]},{"type":"text","value":"). A plethora of projections are available, each with different pros and cons, deforming distances, areas, or angles in different ways. The default “Plate Carrée” projection used above is a so-called "},{"type":"element","tagName":"a","properties":{"href":"https://en.wikipedia.org/wiki/Equirectangular_projection"},"children":[{"type":"text","value":"equirectangular projection"}]},{"type":"text","value":", in which meridians and parallels are always at right angles, but distances and areas can be severely distorted: for instance, on such a map Greenland (410,450 km^2) appears to have the same size as Australia, which in reality is an order of magnitude larger (7,741,220 km2). To quantify this effect, Cartopy’s "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"tissot"}]},{"type":"text","value":" method allows to plot the Tissot’s ellipses of distortion ("},{"type":"element","tagName":"a","properties":{"href":"https://en.wikipedia.org/wiki/Tissot%27s_indicatrix"},"children":[{"type":"text","value":"“indicatrix”"}]},{"type":"text","value":"), like so:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_05"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"You can find a list of supported projections in Cartopy, with examples, "},{"type":"element","tagName":"a","properties":{"href":"https://scitools.org.uk/cartopy/docs/latest/reference/crs.html"},"children":[{"type":"text","value":"https://scitools.org.uk/cartopy/docs/latest/reference/crs.html"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Let us try the Mollweide projection, which is appropriate for thematic world maps illustrating area characteristics and analysis requiring accurate areas. This time, we’ll define an object to store our projection definition. Any time you wish to use this particular projection later in a notebook, you can use the object name rather than repeating the same call to "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"ccrs"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_06"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Exercise 6.1"}]},{"type":"text","value":"\nPick another projection, plot the globe with topography + administrative boundaries, and represent the projection’s distortion using Tissot’s indicatrix. Can you find a projection that accurately represents the area ratio between Greenland and Australia?"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_07"},"children":[{"type":"text","value":"\nLook up projections at https://scitools.org.uk/cartopy/docs/latest/reference/crs.html !\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"Local Maps"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Now, let’s go back to PlateCarree, but let’s use Cartopy’s "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"set_extent"}]},{"type":"text","value":" method to restrict the map coverage. Let’s also choose a lower resolution for coastlines, just to illustrate how one can specify that. And we’ll plot lat/lon lines as well, for good measure. The reference for Natural Earth’s three resolutions (10m, 50m, 110m; higher is coarser) is at "},{"type":"element","tagName":"a","properties":{"href":"https://www.naturalearthdata.com/downloads/"},"children":[{"type":"text","value":"https://www.naturalearthdata.com/downloads/"}]},{"type":"text","value":"."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_08"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":" Note the in the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"set_extent"}]},{"type":"text","value":" call, we specified a "},{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"PlateCarree"}]},{"type":"text","value":" projection. This ensures that the values we passed into "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"set_extent"}]},{"type":"text","value":" will be "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"transformed"}]},{"type":"text","value":" from degrees into the values appropriate for the projection we use for the map (numbers between 0 and 1, in Matplotlib)."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Let us now use these features to create a regional map centered over Ukraine in Lambert Conformal projection. Be patient: with a limited regional extent as specified here, the highest resolution (10m) shapefiles are used; as a result (as with any "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"GeoAxes"}]},{"type":"text","value":" object that must be transformed from one coordinate system to another), this will take longer to plot, particularly if you haven’t previously retrieved these features from the Natural Earth shapefile server."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_09"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"To highlight the country we use "},{"type":"element","tagName":"a","properties":{"href":"https://stackoverflow.com/a/47885128/4984978"},"children":[{"type":"text","value":"this geopandas solution"}]},{"type":"text","value":", and to save ourselves a lot of repeating, we define a function:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_10"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"A common use case for mappping in the paleosciences is to display the location of a point of interest, e.g. the site of sample collection. This is done very easily by re-using Matplotlib functions like "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.text.html?highlight=text#examples-using-matplotlib-axes-axes-text"},"children":[{"type":"text","value":"text"}]},{"type":"text","value":". On the map below we add a dot and a label for the city of Kyiv:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_12"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Now that you know to do it for cities, you can do it for any geolocated sample."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"Plotting a field on the sphere"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"In addition to plotting the location and geographic context of a sampling site, or of a collection of sites, one might want to plot climate fields (e.g. temperature), which vary continuously over time and space.  To simplify matters, let us use NumPy to define a field of our own on a bespoke lat-lon grid, then plot it with (you guessed it) Matplotlib:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_14"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Plotting data on a Cartesian grid is equivalent to plotting data in the Plate Carrée projection, where meridians and parallels are all straight lines with constant spacing. As a result of this simplicity, the global datasets we use often begin in the Plate Carrée projection."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Once we create our map again, we can plot this data as a contour map. We also need to specify the projection we are transforming "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"from"}]},{"type":"text","value":" (i.e. the projection our data is currently in) using the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"transform"}]},{"type":"text","value":" argument. Let’s plot our data in the Mollweide projection to see how shapes change under a transformation."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_15"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Note that "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/3.5.1/api/_as_gen/matplotlib.pyplot.contourf.html"},"children":[{"type":"text","value":"contourf"}]},{"type":"text","value":" and "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/3.5.1/api/_as_gen/matplotlib.pyplot.colorbar.html"},"children":[{"type":"text","value":"colorbar"}]},{"type":"text","value":" are standard Matplotlib functions. As usual, Cartopy only offers a mapping from the regular display on a rectangular set of axes to a projection on the sphere, by specifying "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"projection"}]},{"type":"text","value":" in the creation of the "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"Axes"}]},{"type":"text","value":" object (here, with "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"plt.subplot"}]},{"type":"text","value":", but there are other ways) and by specifying a coordinate mapping ("},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"transform=ccrs.PlateCarree()"}]},{"type":"text","value":") in the call to the plotting function itself (here, "},{"type":"element","tagName":"code","properties":{},"children":[{"type":"text","value":"contourf"}]},{"type":"text","value":"). The lesson is that "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"any"}]},{"type":"text","value":" Matplotlib function can be used on top of Cartopy, allowing to represent virtually anything on the sphere. Oh, and it works on "},{"type":"element","tagName":"a","properties":{"href":"https://github.com/eleanorlutz/mars_geology_atlas_of_space"},"children":[{"type":"text","value":"other planets"}]},{"type":"text","value":", too."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"h3","properties":{},"children":[{"type":"text","value":"The plot thickens: Uniting Time and Space into Cohesive Narratives"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Maps need not be standalone objects; they are often interwoven with other displays to create a cohesive graphical narrative. In other words, every figure tells a story, and as "},{"type":"element","tagName":"a","properties":{"href":"https://www.edwardtufte.com/tufte/"},"children":[{"type":"text","value":"Edward Tufte"}]},{"type":"text","value":" reminds us, stories are often about time and place. In this last exercise we revisit the dataset NINO3 and All-India Rainfall to add a spatial dimension to what was (so far) a purely temporal narrative.  "}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"We start by plotting the two series, and adding a map underneath to provide spatial context:"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_16"},"children":[{"type":"text","value":"\nThis is just a demo. Relax and enjoy!\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"This is an OK plot; that is to say, it is labeled enough to be interpretable, but it won’t make the cover of Nature. Notice how we foolishly used different colors for the variables and their geographic context between the two subplots. Wouldn’t it be "},{"type":"element","tagName":"em","properties":{},"children":[{"type":"text","value":"so"}]},{"type":"text","value":" much better if the colors echoed each other from subplot to subplot, to assert correspondences at the subconscious level? Also, topography is not terribly useful here, and needlessly clutters the plot."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"strong","properties":{},"children":[{"type":"text","value":"Exercise 6.4"}]},{"type":"text","value":"\nColor-coordinate the two plots, using the "},{"type":"element","tagName":"a","properties":{"href":"https://matplotlib.org/stable/tutorials/colors/colors.html?highlight=cn"},"children":[{"type":"text","value":"Cn notation"}]},{"type":"text","value":". Also, flip the map and the timeseries, so the map is on top, and remove topography."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"codeblock","properties":{"id":"06_17"},"children":[{"type":"text","value":"\nSee the previous codeblock and re-use at will! Only a few minor tweaks are needed.\n"}]},{"type":"text","value":"\n"}]},{"type":"text","value":"\n"},{"type":"element","tagName":"exercise","properties":{"id":"11","title":"Getting Started with Jupyter"},"children":[{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Read the following "},{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/foundations/getting-started-jupyter.html"},"children":[{"type":"text","value":"article"}]},{"type":"text","value":" to know more about what Jupyter is."}]},{"type":"text","value":"\n"},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Then, read this "},{"type":"element","tagName":"a","properties":{"href":"https://foundations.projectpythia.org/foundations/jupyterlab.html"},"children":[{"type":"text","value":"link"}]},{"type":"text","value":" to learn particularly about JupyterLab. Follow the exercises on an extra tab/window using the provided "},{"type":"element","tagName":"a","properties":{"href":"https://mybinder.org/v2/gh/ProjectPythia/pythia-foundations/main?urlpath=lab/tree/foundations/jupyterlab.ipynb"},"children":[{"type":"text","value":"Binder"}]}]},{"type":"text","value":"\n"}]}],"data":{"quirksMode":false}},"frontmatter":{"id":1,"title":"Module 1: Intro to Python and Jupyter Notebooks","description":"In this module, you will learn how to write basic Python code  and how to use your Jupyter Notebooks.","next":"/module2","prev":null}}},"pageContext":{"slug":"/module1"}},"staticQueryHashes":["1029480139","1771538597","3063084251","4240431937"]}