{ "cells": [ { "cell_type": "markdown", "source": [ " ### What is an Ensemble?\n", "\n", "First, we need to understand what an ensemble is and how it is structured. In the HEFS API, for a given location ID and parameter ID, a forecast ensemble is a set of forecast time series (ensemble members). Each ensemble member consists of a series of timestep values with a coresponding forecasted value." ], "metadata": { "id": "_4p-_GX4-dmt" } }, { "cell_type": "markdown", "source": [ " ### Retrieving Data from the API\n", "\n", "We need a way to retrieve the data from the API. To achieve this, we first import Python's requests library, which allows us to make HTTP requests. Additionally, we import the pprint function from the pprint library to make the output more readable. Finally, we define the API endpoint we'll be interacting with, setting API_ENDPOINT to https://api.water.noaa.gov/hefs/. Here's how we do it:" ], "metadata": { "id": "Y7KPb6LtihNs" } }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [], "id": "yhYCb2CsSVxg" }, "outputs": [], "source": [ "# start by importing the requests library\n", "import requests\n", "# import the pprint library to make the output more readable\n", "from pprint import pprint\n", "# define the api-endpoint\n", "API_ENDPOINT = \"https://api.water.noaa.gov/hefs\"\n", "LOCATION_ID = \"RUPM8\"\n", "PARAMETER_ID = \"QINE\"" ] }, { "cell_type": "markdown", "metadata": { "id": "lWlt2sycS05l" }, "source": [ "### Most Recent Ensemble Forecast for a Location and Plotting\n", "\n", "In other cases, you might want to retrieve and plot recent ensemble data. The API, unless otherwise specified via a specific date request, will return the most recent ensemble.\n", "\n", "For example, to retrieve the latest QINE ensemble forecast for location id RUPM8, you'll specify `location_id=RUPM8`, `parameter_id=QINE`, and `limit=1`. \n", "\n", "`/v1/ensembles/?location_id={LOCATION_ID}¶meter_id={PARAMETER_ID}&limit=1`\n", "\n", "Where LOCATION_ID and PARAMETER_ID are the location id and parameter id of the request respectively." ] }, { "cell_type": "code", "source": [ "from datetime import datetime, timedelta\n", "# create a series request with location_id, parameter_id, and ordering filters\n", "uri = API_ENDPOINT + f\"/v1/ensembles/?location_id={LOCATION_ID}¶meter_id={PARAMETER_ID}&limit=1\"\n", "# get the response\n", "response = requests.request(\"GET\", uri)\n", "# print the response\n", "pprint(response.json())" ], "metadata": { "id": "d7mnUmBtEguU" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "source": [ "We now use the data above to plot the ensemble forecast. To do this, we must parse through the response data and plot each ensemble member's data points (time/value pairs) onto a single graph. We will use the matplotlib python package to plot the data." ], "metadata": { "id": "GolV7Z0Etds7" } }, { "cell_type": "code", "source": [ "import matplotlib.pyplot as plt\n", "import datetime\n", "\n", "def graph_ensemble_data(response_data):\n", " \"\"\"Graphs ensemble data from a API response.\n", "\n", " Args:\n", " response_data: A dictionary containing the API response data.\n", " \"\"\"\n", " if response_data != []:\n", " # iterate through result in results\n", " for result in response_data[0]:\n", " # check if event is present in response data\n", " if 'events' in result and result['events']:\n", " # iterate through event forcasts in the ensemble api response\n", " for event in result['events']:\n", " # initialize times list\n", " times = []\n", " # initialize values list\n", " values = []\n", " # iterate through values in the sepecific forcast event\n", " for value in result['events']:\n", " if value['value'] is not None and ('miss_val' not in result or value['value'] != result['miss_val']):\n", " # prepare datetime for reformatting\n", " datetime_str = f\"{value['valid_datetime']}\"\n", " datetime_str = datetime_str.replace('T', \" \")\n", " datetime_str = datetime_str.replace('Z', \"\")\n", " # format datetime to Year-Month-Day Hour:Minutes:Seconds\n", " datetime_obj = datetime.datetime.strptime(datetime_str, \"%Y-%m-%d %H:%M:%S\")\n", " # add values from the forecast to their respective lists\n", " times.append(datetime_obj)\n", " values.append(float(value['value']))\n", " # plot the date for the event forecast\n", " #print(\"now\")\n", " plt.plot(times, values)\n", " # set x graph label\n", " plt.xlabel('Time')\n", " # set y graph label\n", " plt.ylabel('Value')\n", " # set graph title\n", " plt.title('Ensemble Data')\n", " # rotate x text vertically for better visibility\n", " plt.xticks(rotation='vertical')\n", " # display the actaul plot\n", " plt.show()\n", "\n", "# call graphing function\n", "graph_ensemble_data(response.json())\n" ], "metadata": { "id": "IPSP1PFqX-pi" }, "execution_count": null, "outputs": [] }, { "cell_type": "markdown", "metadata": { "id": "kn31tBc-SVxj" }, "source": [ "## Summary\n", "\n", "In this notebook, we learned how to use the HEFS API to retrieve the latest ensemble forecast for a given location. We also learned how to use visualize ensemble data using matplotlib.\n", "\n", "To try the ensembles endpoint via swagger go to: https://api.water.noaa.gov/hefs/v1/docs/#/ensembles" ] } ], "metadata": { "kernelspec": { "display_name": "conda_python3", "language": "python", "name": "conda_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.10.13" }, "vscode": { "interpreter": { "hash": "916dbcbb3f70747c44a77c7bcd40155683ae19c65e1c03b4aa3499c5328201f1" } }, "colab": { "provenance": [] } }, "nbformat": 4, "nbformat_minor": 0 }