{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"[](https://colab.research.google.com/github/neuromatch/climate-course-content/blob/main/tutorials/W1D3_RemoteSensing/student/W1D3_Tutorial4.ipynb)
"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Tutorial 4: Understanding Climatology Through Precipitation Data\n",
"\n",
"**Week 1, Day 3, Remote Sensing**\n",
"\n",
"**Content creators:** Douglas Rao\n",
"\n",
"**Content reviewers:** Katrina Dobson, Younkap Nina Duplex, Maria Gonzalez, Will Gregory, Nahid Hasan, Paul Heubel, Sherry Mi, Beatriz Cosenza Muralles, Jenna Pearson, Agustina Pesce, Chi Zhang, Ohad Zivan\n",
"\n",
"**Content editors:** Paul Heubel, Jenna Pearson, Chi Zhang, Ohad Zivan\n",
"\n",
"**Production editors:** Wesley Banfield, Paul Heubel, Jenna Pearson, Konstantine Tsafatinos, Chi Zhang, Ohad Zivan\n",
"\n",
"**Our 2024 Sponsors:** CMIP, NFDI4Earth"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Tutorial Objectives\n",
"\n",
"*Estimated timing of tutorial:* 30 minutes\n",
"\n",
"In this tutorial, you will explore the concept of a climatology, and learn how to leverage it using satellite precipitation data. You have already practiced how to calcuate a climatology using temperature data in the overview of the climate system day. That data spanned only 14 years, and typically you would want your data to span at least 30 years to calculate a climatology. Here you will use data spanning several decades to explore the seasonal cycle of precipitation at a specific location.\n",
"\n",
"Upon completing this tutorial, you'll be able to:\n",
"\n",
"- Comprehend the fundamentals of climatologies.\n",
"- Compute a climatology utilizing long-term satellite precipitation data.\n",
"- Create informative maps including features such as projections, coastlines, and other advanced plotting components.\n",
"\n",
"Throughout this tutorial, you'll employ NOAA's monthly precipitation climate data records as the primary resource to demonstrate the process of calculating a long-term climatology for climate analysis. Specifically, you'll use the [Global Precipitation Climatology Project (GPCP) Monthly Precipitation Climate Data Record (CDR)](https://www.ncei.noaa.gov/products/climate-data-records/precipitation-gpcp-monthly). As part of your investigation, you'll focus on a specific location, observing its data across the entire time duration covered by the GPCP monthly dataset."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": [
"colab"
]
},
"outputs": [],
"source": [
"# installations ( uncomment and run this cell ONLY when using google colab or kaggle )\n",
"\n",
"# !pip install s3fs --quiet\n",
"\n",
"# # properly install cartopy in colab to avoid session crash\n",
"# !apt-get install libproj-dev proj-data proj-bin --quiet\n",
"# !apt-get install libgeos-dev --quiet\n",
"# !pip install cython --quiet\n",
"# !pip install cartopy --quiet\n",
"\n",
"# !apt-get -qq install python-cartopy python3-cartopy --quiet\n",
"# !pip uninstall -y shapely --quiet\n",
"# !pip install shapely --no-binary shapely --quiet\n",
"\n",
"# !pip install boto3 --quiet\n",
"\n",
"# you may need to restart the runtime after running this cell and that is ok"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# imports\n",
"import s3fs\n",
"import xarray as xr\n",
"import matplotlib.pyplot as plt\n",
"import cartopy.crs as ccrs\n",
"import boto3\n",
"import botocore\n",
"import pooch\n",
"import os\n",
"import tempfile"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Install and import feedback gadget\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Install and import feedback gadget\n",
"\n",
"!pip3 install vibecheck datatops --quiet\n",
"\n",
"from vibecheck import DatatopsContentReviewContainer\n",
"def content_review(notebook_section: str):\n",
" return DatatopsContentReviewContainer(\n",
" \"\", # No text prompt\n",
" notebook_section,\n",
" {\n",
" \"url\": \"https://pmyvdlilci.execute-api.us-east-1.amazonaws.com/klab\",\n",
" \"name\": \"comptools_4clim\",\n",
" \"user_key\": \"l5jpxuee\",\n",
" },\n",
" ).render()\n",
"\n",
"\n",
"feedback_prefix = \"W1D3_T4\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Figure Settings\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Figure Settings\n",
"import ipywidgets as widgets # interactive display\n",
"\n",
"%config InlineBackend.figure_format = 'retina'\n",
"plt.style.use(\n",
" \"https://raw.githubusercontent.com/neuromatch/climate-course-content/main/cma.mplstyle\"\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Helper functions\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Helper functions\n",
"\n",
"def pooch_load(filelocation=None, filename=None, processor=None):\n",
" shared_location = \"/home/jovyan/shared/data/tutorials/W1D3_RemoteSensing\" # this is different for each day\n",
" user_temp_cache = tempfile.gettempdir()\n",
"\n",
" if os.path.exists(os.path.join(shared_location, filename)):\n",
" file = os.path.join(shared_location, filename)\n",
" else:\n",
" file = pooch.retrieve(\n",
" filelocation,\n",
" known_hash=None,\n",
" fname=os.path.join(user_temp_cache, filename),\n",
" processor=processor,\n",
" )\n",
"\n",
" return file"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Video 1: Understanding Climatology\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @title Video 1: Understanding Climatology\n",
"\n",
"from ipywidgets import widgets\n",
"from IPython.display import YouTubeVideo\n",
"from IPython.display import IFrame\n",
"from IPython.display import display\n",
"\n",
"\n",
"class PlayVideo(IFrame):\n",
" def __init__(self, id, source, page=1, width=400, height=300, **kwargs):\n",
" self.id = id\n",
" if source == 'Bilibili':\n",
" src = f'https://player.bilibili.com/player.html?bvid={id}&page={page}'\n",
" elif source == 'Osf':\n",
" src = f'https://mfr.ca-1.osf.io/render?url=https://osf.io/download/{id}/?direct%26mode=render'\n",
" super(PlayVideo, self).__init__(src, width, height, **kwargs)\n",
"\n",
"\n",
"def display_videos(video_ids, W=400, H=300, fs=1):\n",
" tab_contents = []\n",
" for i, video_id in enumerate(video_ids):\n",
" out = widgets.Output()\n",
" with out:\n",
" if video_ids[i][0] == 'Youtube':\n",
" video = YouTubeVideo(id=video_ids[i][1], width=W,\n",
" height=H, fs=fs, rel=0)\n",
" print(f'Video available at https://youtube.com/watch?v={video.id}')\n",
" else:\n",
" video = PlayVideo(id=video_ids[i][1], source=video_ids[i][0], width=W,\n",
" height=H, fs=fs, autoplay=False)\n",
" if video_ids[i][0] == 'Bilibili':\n",
" print(f'Video available at https://www.bilibili.com/video/{video.id}')\n",
" elif video_ids[i][0] == 'Osf':\n",
" print(f'Video available at https://osf.io/{video.id}')\n",
" display(video)\n",
" tab_contents.append(out)\n",
" return tab_contents\n",
"\n",
"\n",
"video_ids = [('Youtube', 'lIOVdzlnT60'), ('Bilibili', 'BV19X4y1e7iJ')]\n",
"tab_contents = display_videos(video_ids, W=730, H=410)\n",
"tabs = widgets.Tab()\n",
"tabs.children = tab_contents\n",
"for i in range(len(tab_contents)):\n",
" tabs.set_title(i, video_ids[i][0])\n",
"display(tabs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Understanding_Climatology_Video\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"pycharm": {
"name": "#%%\n"
},
"tags": [
"remove-input"
]
},
"outputs": [],
"source": [
"# @markdown\n",
"from ipywidgets import widgets\n",
"from IPython.display import IFrame\n",
"\n",
"link_id = \"2ak68\"\n",
"\n",
"print(f\"If you want to download the slides: https://osf.io/download/{link_id}/\")\n",
"IFrame(src=f\"https://mfr.ca-1.osf.io/render?url=https://osf.io/{link_id}/?direct%26mode=render%26action=download%26mode=render\", width=854, height=480)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Understanding_Climatology_Slides\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Section 1: Obtain Monthly Precipitation Data\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"In this tutorial, the objective is to demonstrate how to calculate the long-term precipitation climatology using monthly precipitation climate data records from NOAA. \n",
"\n",
"You'll be utilizing the [Global Precipitation Climatology Project (GPCP) Monthly Precipitation Climate Data Record (CDR)](https://www.ncei.noaa.gov/products/climate-data-records/precipitation-gpcp-monthly). This dataset contains monthly satellite-gauge data and corresponding precipitation error estimates from January 1979 to the present, gridded at a 2.5°×2.5° resolution. *Satellite-gauge* means that the climate data record (CDR) is a compilation of precipitation data from multiple satellites and in-situ sources, combined into a final product that optimizes the advantages of each type of data.\n",
"\n",
"While a higher spatial resolution (1°×1°) at daily resolution exists for varied applications, we will restrict ourselves to the coarser resolution monthly data due to computational limitations. However, you are encouraged to delve into the daily higher resolution data for your specific project needs.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.1: Access GPCP Monthly CDR Data on AWS\n",
"\n",
"To perform analysis, we will need to access the monthly data files from AWS first. We will use the skills that we learned in Tutorial 3 on accessing data from an AWS S3 bucket."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# connect to the AWS S3 bucket for the GPCP Monthly Precipitation CDR data\n",
"fs = s3fs.S3FileSystem(anon=True)\n",
"\n",
"# get the list of all data files in the AWS S3 bucket fit the data file pattern.\n",
"file_pattern = \"noaa-cdr-precip-gpcp-monthly-pds/data/*/gpcp_v02r03_monthly_*.nc\"\n",
"file_location = fs.glob(file_pattern)\n",
"file_location[0:3]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"print(\"Total number of GPCP Monthly precipitation data files:\")\n",
"print(len(file_location))"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"We have more than 500 GPCP monthly precipitation CDR data files in the AWS S3 bucket. Each data file contains the data of each month globally starting from January 1979. Now, let's open a single data file to look at the data structure before we open all data files."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# first, open a client connection\n",
"client = boto3.client(\n",
" \"s3\", config=botocore.client.Config(signature_version=botocore.UNSIGNED)\n",
") # initialize aws s3 bucket client\n",
"\n",
"# read single data file to understand the file structure\n",
"# ds_single = xr.open_dataset(pooch.retrieve('http://s3.amazonaws.com/'+file_location[0],known_hash=None )) # open the file\n",
"ds_single = xr.open_dataset(\n",
" pooch_load(\n",
" filelocation=\"http://s3.amazonaws.com/\" + file_location[0],\n",
" filename=file_location[0],\n",
" )\n",
")\n",
"# check how many variables are included in one data file\n",
"ds_single.data_vars"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"From the information provided by `xarray`, there are a total of five data variables in this monthly data file, including `precip` for the monthly precipitation and `precip_error` for the monthly precipitation error.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# check the coordinates for the data file\n",
"ds_single.coords"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"All data is organized in three dimensions: `latitude`, `longitude`, and `time`. We want to create a three-dimensional data array for the monthly precipitation data across the entire data period (from January 1979 until present) so we must open all the available files"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# open all the monthly data files\n",
"# this process will take ~ 5 minute to complete due to the number of data files.\n",
"\n",
"# file_ob = [pooch.retrieve('http://s3.amazonaws.com/'+file,known_hash=None ) for file in file_location]\n",
"file_ob = [\n",
" pooch_load(filelocation=\"http://s3.amazonaws.com/\" + file, filename=file)\n",
" for file in file_location\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# using this function instead of 'open_dataset' will concatenate the data along the dimension we specify\n",
"ds = xr.open_mfdataset(file_ob, combine=\"nested\", concat_dim=\"time\")\n",
"\n",
"# comment for colab users only: this could toss an error message for you.\n",
"# you should still be able to use the dataset with this error just not print ds\n",
"# you can try uncommenting the following line to avoid the error\n",
"# ds.attrs['history']='' # the history attribute have unique chars that cause a crash on Google colab.\n",
"ds"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"In the above code, we used `combine='nested', concat_dim='time'` to combine all monthly precipitation data into one data array along the dimension of `time`. This command is very useful when reading in multiple data files of the same structure but covering different parts of the full data record.\n",
"\n",
"Since we are interested in the precipitation data globally at this moment, let's extract the entire data array of precipitation from the entire dataset."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# examine the precipitation data variable\n",
"precip = ds.precip\n",
"precip"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"As you can see, the data array has the dimensions of `time` `longitude` `latitude`. Before delving into further analysis, let's visualize the precipitation data to gain a better understanding of its patterns and characteristics. "
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 1.2: Visualize GPCP Data Using Cartopy"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"In previous tutorials, we've learned how to make simple visualization using `matplotlib` using `latitude` and `longitude` as the y-axis and x-axis."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# create simple map of the GPCP precipitation data using matplotlib\n",
"fig, ax = plt.subplots()\n",
"\n",
"# use the first month of data as an example\n",
"precip.sel(time=\"1979-01-01\").plot(ax=ax)"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"From the figure, the boundary between land and ocean, especially for North and South America, can be observed vaguely. However, this visualization is not ideal as it requires some guesswork in identifying the specific regions. To overcome this limitation and enhance the visualization, we will employ `cartopy`, a library that offers advanced mapping features. With `cartopy`, we can incorporate additional elements such as coastlines, major grid markings, and specific map projections."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# visualize the precipitation data of a selected month using cartopy\n",
"\n",
"# select data for the month of interest\n",
"data = precip.sel(time=\"1979-01-01\", method=\"nearest\")\n",
"\n",
"# initiate plot, note that it is possible to change the size of the figure,\n",
"# which is already defined within the \"cma.mplstyle\" file in the 'Figure Settings' cell above\n",
"fig, ax = plt.subplots(subplot_kw={\"projection\": ccrs.Robinson()},\n",
" #figsize=(9, 6)\n",
" )\n",
"\n",
"# add coastlines to indicate land/ocean\n",
"ax.coastlines()\n",
"\n",
"# add major grid lines for latitude and longitude\n",
"ax.gridlines()\n",
"\n",
"# add the precipitation data with map projection transformation\n",
"# also specify the maximum 'vmax' and minimum value 'vmin' or set 'robust=True' to increase the\n",
"# contrast in the map.\n",
"data.plot(\n",
" ax=ax,\n",
" transform=ccrs.PlateCarree(),\n",
" #vmin=0,\n",
" #vmax=20,\n",
" robust=True,\n",
" cbar_kwargs=dict(shrink=0.5, label=\"GPCP Monthly Precipitation \\n(mm/day)\"),\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"The updated map provides significant improvements, offering us a wealth of information to enhance our understanding of the GPCP monthly precipitation data. From the visualization, we can observe that regions such as the Amazon rainforest, the northern part of Australia, and other tropical areas exhibited higher levels of monthly precipitation in January 1979. These patterns align with our basic geographical knowledge, reinforcing the validity of the data and representation."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Coding Exercises 1.2\n",
"Remember the GPCP also offers a data variable that documents the error of the monthly precipitation data used above. This error information is valuable for understanding the level of confidence we can place on the data. \n",
"\n",
"1. Generate the precipitation error for the same month (1979-01-01) using the examples provided above."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# select data for the month of interest\n",
"data = ...\n",
"\n",
"# initiate plot\n",
"fig, ax = plt.subplots(subplot_kw={\"projection\": ccrs.Robinson()})\n",
"\n",
"# add coastal lines to indicate land/ocean\n",
"_ = ...\n",
"\n",
"# add grid lines for latitude and longitude\n",
"_ = ...\n",
"\n",
"# add the precipitation data\n",
"_ = ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {},
"tags": []
},
"source": [
"[*Click for solution*](https://github.com/neuromatch/climate-course-content/tree/main/tutorials/W1D3_RemoteSensing/solutions/W1D3_Tutorial4_Solution_8041e1ae.py)\n",
"\n",
"*Example output:*\n",
"\n",
"
\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Coding_Exercise_1_2\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Questions 1.2: Climate Connection"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"1. Comment on the spatial pattern of the precipitation error provided by GPCP CDR data for this specific month. \n",
"2. Which areas have the highest errors? Why do you think this might be?"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {},
"tags": []
},
"source": [
"[*Click for solution*](https://github.com/neuromatch/climate-course-content/tree/main/tutorials/W1D3_RemoteSensing/solutions/W1D3_Tutorial4_Solution_de0347ea.py)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Questions_1_2\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Section 2: Climatology"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {},
"tags": []
},
"source": [
"## Section 2.1: Plot Time Series of Data at a Specific Location"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"We have over 40 years of monthly precipitation data. Let's examine a specific location throughout the entire time span covered by the GPCP monthly data. For this purpose, we will focus on the data point located at (0°N, 0°E)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# select the entire time series for the grid that contains the location of (0N, 0E)\n",
"grid = ds.precip.sel(latitude=0, longitude=0, method=\"nearest\")\n",
"\n",
"# initiate plot\n",
"fig, ax = plt.subplots()\n",
"\n",
"# plot the data\n",
"grid.plot(ax=ax)\n",
"\n",
"# remove the automatically generated title\n",
"ax.set_title(\"\")\n",
"\n",
"# add a grid\n",
"ax.grid(True)\n",
"\n",
"# edit default axis labels\n",
"ax.set_xlabel(\"Time (months)\")\n",
"ax.set_ylabel(\"GPCP Monthly Precipitation \\n(mm/day)\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"From the time series plot, note a repeating pattern with a seasonal cycle (roughly the same ups and downs over the course of a year, for each year). In previous tutorials during the climate system overview, you learned how to calculate a climatology. We can apply this same calculation to the precipitation CDR data to investigate the annual cycle of precipitation at this location."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"## Section 2.2: Calculate the Climatology\n",
"\n",
"As a refresher, a climatology typically employs a 30-year time period for the calculation. In this case, let's use the reference period of 1981-2010."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# first, let's extract the data for the time period that we want (1981-2010)\n",
"precip_30yr = ds.precip.sel(time=slice(\"1981-01-01\", \"2010-12-30\"))\n",
"precip_30yr"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Now we can use Xarray's [`.groupby()`](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.groupby.html) functionality to calculate the monthly climatology.\n",
"\n",
"Recall that `.groupby()` splits the data based on a specific criterion (in this case, the month of the year) and then applies a process (in our case, calculating the mean value across 30 years for that specific month) to each group before recombining the data together."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# use .groupby() to calculate monthly climatology (1981-2010)\n",
"precip_clim = precip_30yr.groupby(\"time.month\").mean(dim=\"time\")\n",
"precip_clim"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"With the resulting climatology data array, we can make a set of maps to visualize the monthly climatology from four different seasons."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# define the figure and each axis for the 2 rows and 2 columns\n",
"fig, axs = plt.subplots(\n",
" nrows=2, ncols=2, subplot_kw={\"projection\": ccrs.Robinson()}, figsize=(12, 8)\n",
")\n",
"\n",
"# axs is a 2-dimensional array of `GeoAxes`. We will flatten it into a 1-D array to loop over it\n",
"axs = axs.flatten()\n",
"\n",
"# loop over selected months (Jan, Apr, Jul, Oct)\n",
"for i, month in enumerate([1, 4, 7, 10]):\n",
"\n",
" # Draw the coastlines and major gridline for each subplot\n",
" axs[i].coastlines()\n",
" axs[i].gridlines()\n",
"\n",
" # Draw the precipitation data\n",
" precip_clim.sel(month=month).plot(\n",
" ax=axs[i],\n",
" transform=ccrs.PlateCarree(),\n",
" vmin=0,\n",
" vmax=15, # use the same range of max and min value\n",
" cbar_kwargs=dict(shrink=0.5, label=\"GPCP Climatology\\n(mm/day)\"),\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"In the seasonal collection of the climatology map, we can observe a clear pattern of precipitation across the globe. The tropics exhibit a higher amount of precipitation compared to other regions. Additionally, the map illustrates the seasonal patterns of precipitation changes across different regions of the globe, including areas influenced by monsoons."
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Questions 2.2: Climate Connection\n",
"\n",
"1. Do the tropics or high latitudes receive more precipitation all year round? Why do you think this is? Think back to the climate system overview tutorials on atmospheric circulation to help form your answer.\n",
"2. In the climate system overview tutorials you learned about Monsoon systems in places such as India, Southeast Asia, and East Africa where there are notable wet and dry seasons. Do you see evidence of say, the Indian monsoon, in these maps?"
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {},
"tags": []
},
"source": [
"[*Click for solution*](https://github.com/neuromatch/climate-course-content/tree/main/tutorials/W1D3_RemoteSensing/solutions/W1D3_Tutorial4_Solution_213928a9.py)\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Questions_2_2\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Now let's examine the climatology of the location we previously analyzed throughout the entire time series, specifically at (0°N, 0°E)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# initiate plot\n",
"fig, ax = plt.subplots()\n",
"\n",
"# select location and add to plot\n",
"precip_clim.sel(latitude=0, longitude=0, method=\"nearest\").plot(ax=ax)\n",
"\n",
"# remove the automatically generated title\n",
"ax.set_title(\"\")\n",
"# add a grid\n",
"ax.grid(True)\n",
"# edit default axis labels\n",
"ax.set_xlabel(\"Time (months)\")\n",
"ax.set_ylabel(\"GPCP Monthly Precipitation \\n(mm/day)\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"\n",
"The monthly climatology time series for the point of interest demonstrates a noticeable seasonal pattern, with dry and rainy months observed in the region. Precipitation is typically more abundant between December and May, while August experiences the driest conditions throughout the year.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"### Coding Exercises 2.2\n",
"\n",
"As climate changes, the climatology of precipitation may also change. In fact, climate researchers recalculate a climatology every 10 years. This allows them to monitor how the norms of our climate system change. In this exercise, you will visualize how the climatology of our dataset changes depending on the reference period used.\n",
"\n",
"1. Calculate the climatology for a different reference period (1991-2020) and compare it to the climatology that we just generated with the reference period (1981-2010). Be sure to compare the two and note the differences. Can you see why it is important to re-calculate this climatology?\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"execution": {},
"tags": []
},
"outputs": [],
"source": [
"# extract 30 year data for 1991-2020\n",
"precip_30yr_exercise = ...\n",
"\n",
"# calculate climatology for 1991-2020\n",
"precip_clim_exercise = ...\n",
"\n",
"# find difference in climatologies: (1981-2010) minus (1991-2020)\n",
"precip_diff_exercise = ...\n",
"\n",
"# Compare the climatology for four different seasons by generating the\n",
"# difference maps for January, April, July, and October with colorbar max and min = 1,-1\n",
"\n",
"# Define the figure and each axis for the 2 rows and 2 columns\n",
"fig, axs = plt.subplots(\n",
" nrows=2, ncols=2, subplot_kw={\"projection\": ccrs.Robinson()}#, figsize=(12, 8)\n",
")\n",
"\n",
"# axs is a 2-dimensional array of `GeoAxes`. We will flatten it into a 1-D array\n",
"axs = ...\n",
"\n",
"# Loop over selected months (Jan, Apr, Jul, Oct)\n",
"for i, month in enumerate([1, 4, 7, 10]):\n",
" ..."
]
},
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"execution": {},
"tags": []
},
"source": [
"[*Click for solution*](https://github.com/neuromatch/climate-course-content/tree/main/tutorials/W1D3_RemoteSensing/solutions/W1D3_Tutorial4_Solution_f1c5c17b.py)\n",
"\n",
"*Example output:*\n",
"\n",
"
\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Submit your feedback\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"cellView": "form",
"execution": {},
"tags": [
"hide-input"
]
},
"outputs": [],
"source": [
"# @title Submit your feedback\n",
"content_review(f\"{feedback_prefix}_Coding_Exercise_2_2\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Summary\n",
"\n",
"Climatologies provide valuable insight into the typical weather patterns of a region. Key takeaways from this tutorial include:\n",
"\n",
"- A climatology pertains to the long-term average of various system attributes, such as temperature and precipitation, often spanning 30 years.\n",
"- Satellite climate data records offer valuable insights for calculating climatologies on a global scale.\n",
"\n",
"By comparing the weather conditions of a specific day or month to the climatology, we can determine the extent to which they deviate from the norm. This concept of comparing against the climatology, or the norm, will be the focus of our next tutorial - the anomaly!"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"# Resources"
]
},
{
"cell_type": "markdown",
"metadata": {
"execution": {}
},
"source": [
"Data from this tutorial can be accessed [here](https://noaa-cdr-precip-gpcp-monthly-pds.s3.amazonaws.com/index.html#data/)."
]
}
],
"metadata": {
"colab": {
"collapsed_sections": [],
"include_colab_link": true,
"name": "W1D3_Tutorial4",
"provenance": [],
"toc_visible": true
},
"kernel": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.19"
}
},
"nbformat": 4,
"nbformat_minor": 4
}