{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "## CFSR Data and Graphics Preparation for the Science-on-a-Sphere" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook will create all the necessary files and directories for a visualization on NOAA's Science-on-a-Sphere. For this example, we will produce a map of 850 hPa geopotential heights, temperature, and horizontal wind and sea-level pressure, using the Climate Forecast System Reanalysis (CFSR), for the March 13-14 1993 winter storm, aka **Superstorm '93**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Overview:\n", "\n", "1. Set up output directories for SoS\n", "1. Specify the date/time range for your case\n", "1. Use Cartopy's `add_cyclic_point` method to avoid a blank seam at the dateline\n", "1. Create small and large thumbnail graphics.\n", "1. Create a standalone colorbar\n", "1. Create a set of labels for each plot\n", "1. Create 24 hours worth of Science-on-a-Sphere-ready plots\n", "1. Create an SoS playlist file\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prerequisites\n", "\n", "| Concepts | Importance | Notes |\n", "| --- | --- | --- |\n", "| Matplotlib | Necessary | |\n", "| Cartopy | Necessary | |\n", "| Xarray | Necessary | |\n", "| Metpy | Necessary | |\n", "| Linux command line / directory structure | Helpful | |\n", "\n", "* **Time to learn**: 30 minutes\n", "***" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Imports" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import xarray as xr\n", "import numpy as np\n", "import pandas as pd\n", "import cartopy.feature as cfeature\n", "import cartopy.crs as ccrs\n", "import cartopy.util as cutil\n", "from datetime import datetime as dt\n", "import warnings\n", "import metpy.calc as mpcalc\n", "from metpy.units import units\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do not output warning messages" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "warnings.simplefilter(\"ignore\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Set up output directories for SoS" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The software that serves output for the Science-on-a-Sphere expects a directory structure as follows:\n", "- Top level directory: choose a name that is consistent with your case, e.g.: **SS93**\n", "- 2nd level directory: choose a name that is consistent with the graphic, e.g.: **SLP_500Z**\n", "- 3rd level directories: \n", " - **2048**: Contains the graphics (resolution: 2048x1024) that this notebook generates\n", " - **labels**: Contains one or two files:\n", " 1. (required) A text file, `labels.txt`, which has as many lines as there are graphics in the **2048** file. Each line functions as the title of each graphic. \n", " 1. (optional) A PNG file, `colorbar.png`, which colorbar which will get overlaid on your map graphic.\n", " - **media**: Contains large and small thumbnails (`thumbnail_small.jpg`, `thumbnail_large.jpg`) that serve as icons on the SoS iPad and SoS computer apps\n", " - **playlist**: A text file, `playlist.sos`, which tells the SoS how to display your product\n", " \n", "As an example, here is how the directory structure on our SoS looks for the products generated by this notebook. Our SoS computer stores locally-produced content in the `/shared/sos/media/site-custom` directory (note: the SoS directories are not network-accessible, so you won't be able to `cd` into them). The CFSR visualizations go in the `CFSR` subfolder. Your top-level directory sits within the `CFSR` folder.\n", "\n", "```\n", "sos@sos1:/shared/sos/media/site-custom/CFSR/cle_superbomb/SLP_500Z$ ls -R\n", ".:\n", "2048 labels media playlist\n", "\n", "./2048:\n", "CFSR_1978012600-fs8.png CFSR_1978012606-fs8.png CFSR_1978012612-fs8.png CFSR_1978012618-fs8.png\n", "CFSR_1978012601-fs8.png CFSR_1978012607-fs8.png CFSR_1978012613-fs8.png CFSR_1978012619-fs8.png\n", "CFSR_1978012602-fs8.png CFSR_1978012608-fs8.png CFSR_1978012614-fs8.png CFSR_1978012620-fs8.png\n", "CFSR_1978012603-fs8.png CFSR_1978012609-fs8.png CFSR_1978012615-fs8.png CFSR_1978012621-fs8.png\n", "CFSR_1978012604-fs8.png CFSR_1978012610-fs8.png CFSR_1978012616-fs8.png CFSR_1978012622-fs8.png\n", "CFSR_1978012605-fs8.png CFSR_1978012611-fs8.png CFSR_1978012617-fs8.png CFSR_1978012623-fs8.png\n", "\n", "./labels:\n", "colorbar.png labels.txt\n", "\n", "./media:\n", "thumbnail_big.jpg thumbnail_small.jpg\n", "\n", "./playlist:\n", "playlist.sos\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define the 1st and 2nd-level directories." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# You define these\n", "caseDir = 'SS1993'\n", "prodDir = '850T_Z_Wind'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The 3rd-level directories follow from the 1st and 2nd." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# These remain as is\n", "graphicsDir = caseDir + '/' + prodDir + '/2048/'\n", "labelsDir = caseDir + '/' + prodDir + '/labels/'\n", "mediaDir = caseDir + '/' + prodDir + '/media/'\n", "playlistDir = caseDir + '/' + prodDir + '/playlist/'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create these directories via a Linux command" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "! mkdir -p {graphicsDir} {labelsDir} {mediaDir} {playlistDir}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
!
magic indicates that what follows is a Linux command.-p
option for mkdir
will create all subdirectories, and also will do nothing if the directories already exist.add_cyclic_point
method to eliminate the resulting seam.Axes
. We don't want that included on the sphere-projected graphic either.nFrames
to nTimes so all times are processed.