{ "cells": [ { "cell_type": "markdown", "id": "f9507824", "metadata": {}, "source": [ "# AirNow and UFS-CHEM\n", "\n", "Our first example will demonstrate the basics available in MELODIES MONET to \n", "compare the meteorological capabilities of UFS-CHEM results against AirNow surface observations. We will analyze variables including ozone, temperature, windspeed, and wind direction.\n", "\n", "First, we import the {mod}`melodies_monet.driver` module." ] }, { "cell_type": "code", "execution_count": 1, "id": "3d43faf7", "metadata": {}, "outputs": [], "source": [ "from melodies_monet import driver" ] }, { "cell_type": "markdown", "id": "94ac7f4a", "metadata": {}, "source": [ "## Analysis driver class\n", "\n", "Now, lets create an instance of the analysis driver class, {class}`melodies_monet.driver.analysis`.\n", "It consists of these main parts:\n", "* model instances\n", "* observation instances\n", "* a paired instance of both" ] }, { "cell_type": "code", "execution_count": 2, "id": "7530b948", "metadata": {}, "outputs": [], "source": [ "an = driver.analysis()" ] }, { "cell_type": "markdown", "id": "5986249b", "metadata": {}, "source": [ "Initially, most of our {class}`~melodies_monet.driver.analysis` object's attributes\n", "are set to ``None``, though some have meaningful defaults:" ] }, { "cell_type": "code", "execution_count": 3, "id": "dbed05e8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "analysis(\n", " control='control.yaml',\n", " control_dict=None,\n", " models={},\n", " obs={},\n", " paired={},\n", " start_time=None,\n", " end_time=None,\n", " time_intervals=None,\n", " download_maps=True,\n", " output_dir=None,\n", " output_dir_save=None,\n", " output_dir_read=None,\n", " debug=False,\n", " save=None,\n", " read=None,\n", " regrid=False,\n", ")" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "an" ] }, { "cell_type": "markdown", "id": "2e875aab", "metadata": {}, "source": [ "## Control file\n", "\n", "We set the YAML control file and begin by reading the file.\n", "\n", "```{note}\n", "Check out the {doc}`/appendix/yaml` for info on how to create\n", "and modify these files.\n", "```" ] }, { "cell_type": "code", "execution_count": 4, "id": "367c092f", "metadata": { "tags": [ "hide-output" ] }, "outputs": [ { "data": { "text/plain": [ "{'analysis': {'start_time': '2017-07-01-00:00:00',\n", " 'end_time': '2017-07-03-00:00:00',\n", " 'output_dir': './output/airnow_ufschem',\n", " 'debug': True},\n", " 'model': {'ufschem_v1': {'files': 'example:ufschem:2017-07',\n", " 'files_surf': 'example:ufschem:2017-07_sfc',\n", " 'mod_type': 'ufs',\n", " 'is_global': True,\n", " 'mod_kwargs': {'surf_only': True,\n", " 'sfc_varlist': ['tmp2m', 'spfh2m', 'ugrd10m', 'vgrd10m']},\n", " 'radius_of_influence': 100000,\n", " 'extra_calc': {'rel_hum': {'pres_calc': 'surfpres_pa',\n", " 'specific_hum': 'spfh2m',\n", " 'temp_calc': 'tmp2m'},\n", " 'windspeed': {'u_comp': 'ugrd10m', 'v_comp': 'vgrd10m'},\n", " 'winddir': {'u_comp': 'ugrd10m', 'v_comp': 'vgrd10m'},\n", " 'wind_barb': {'u_comp': 'ugrd10m', 'v_comp': 'vgrd10m'},\n", " 'rose_plot': {'model_wdir': 'winddir', 'model_wspd': 'windspeed'}},\n", " 'mapping': {'airnow': {'o3': 'OZONE',\n", " 'tmp2m': 'TEMP',\n", " 'windspeed': 'WS',\n", " 'rel_hum': 'RHUM'}},\n", " 'projection': None,\n", " 'plot_kwargs': {'color': 'magenta', 'marker': 's', 'linestyle': '-'}}},\n", " 'obs': {'airnow': {'use_airnow': True,\n", " 'filename': 'example:airnow:2017-07',\n", " 'obs_type': 'pt_sfc',\n", " 'variables': {'OZONE': {'unit_scale': 1,\n", " 'unit_scale_method': '*',\n", " 'nan_value': -1.0,\n", " 'ylabel_plot': 'Ozone (ppbv)',\n", " 'xlabel_plot': 'Ozone (ppbv)',\n", " 'vmin_plot': 0.0,\n", " 'vmax_plot': 80,\n", " 'vdiff_plot': 20.0,\n", " 'nlevels_plot': 21},\n", " 'TEMP': {'unit_scale': 273.15,\n", " 'unit_scale_method': '+',\n", " 'nan_value': -1.0,\n", " 'ylabel_plot': 'Temperature 2m (K)',\n", " 'xlabel_plot': 'Temperature 2m (K)',\n", " 'vmin_plot': 275,\n", " 'vmax_plot': 320,\n", " 'vdiff_plot': 20.0,\n", " 'nlevels_plot': 21},\n", " 'WS': {'unit_scale': 1,\n", " 'unit_scale_method': '*',\n", " 'nan_value': -1.0,\n", " 'ylabel_plot': 'Windspeed 10m (m/s)',\n", " 'xlabel_plot': 'Windspeed 10m (m/s)',\n", " 'vmin_plot': 0,\n", " 'vmax_plot': 10,\n", " 'vdiff_plot': 4,\n", " 'nlevels_plot': 18},\n", " 'WD': {'unit_scale': 1,\n", " 'unit_scale_method': '*',\n", " 'nan_value': -1.0,\n", " 'ylabel_plot': 'Wind Direction 10m (deg)',\n", " 'xlabel_plot': 'Wind Direction 10m (deg)',\n", " 'vmin_plot': 0,\n", " 'vmax_plot': 380,\n", " 'vdiff_plot': 3,\n", " 'nlevels_plot': 18},\n", " 'RHUM': {'unit_scale': 1,\n", " 'unit_scale_method': '*',\n", " 'nan_value': -1.0,\n", " 'ylabel_plot': 'Relative Humidity 2m (%)',\n", " 'xlabel_plot': 'Relative Humidity 2m (%)',\n", " 'vmin_plot': 0,\n", " 'vmax_plot': 100,\n", " 'vdiff_plot': 15,\n", " 'nlevels_plot': 8}},\n", " 'extra_calc': {'rose_plot': {'obs_wdir': 'WD', 'obs_wspd': 'WS'}}}},\n", " 'plots': {'plot_grp1': {'type': 'timeseries',\n", " 'fig_kwargs': {'figsize': [12, 6]},\n", " 'default_plot_kwargs': {'linewidth': 2.0, 'markersize': 10.0},\n", " 'text_kwargs': {'fontsize': 24.0},\n", " 'domain_type': ['state_name', 'epa_region'],\n", " 'domain_name': ['MI', 'R5'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'data_proc': {'rem_obs_nan': True,\n", " 'ts_select_time': 'time_local',\n", " 'ts_avg_window': 'h',\n", " 'set_axis': True}},\n", " 'plot_grp1a': {'type': 'timeseries',\n", " 'fig_kwargs': {'figsize': [12, 6]},\n", " 'default_plot_kwargs': {'linewidth': 2.0, 'markersize': 10.0},\n", " 'text_kwargs': {'fontsize': 24.0},\n", " 'domain_type': ['state_name', 'epa_region'],\n", " 'domain_name': ['MI', 'R5'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'data_proc': {'rem_obs_nan': True,\n", " 'ts_select_time': 'time_local',\n", " 'ts_avg_window': 'h',\n", " 'set_axis': True,\n", " 'filter_string': 'WS != 0 and WD != 0'}},\n", " 'plot_grp2': {'type': 'spatial_bias',\n", " 'fig_kwargs': {'states': True, 'figsize': [10, 5]},\n", " 'text_kwargs': {'fontsize': 16.0},\n", " 'domain_type': ['state_name', 'epa_region'],\n", " 'domain_name': ['MI', 'R5'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': True, 'wind_barb': True}},\n", " 'plot_grp3': {'type': 'spatial_overlay',\n", " 'fig_kwargs': {'states': True, 'figsize': [10, 5]},\n", " 'text_kwargs': {'fontsize': 16.0},\n", " 'domain_type': ['epa_region', 'siteid'],\n", " 'domain_name': ['R5', '260810020'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'data_proc': {'rem_obs_nan': True,\n", " 'set_axis': True,\n", " 'wind_barb': True,\n", " 'wind_barb_step': 2,\n", " 'wind_barb_kwargs': {'length': 6, 'linewidth': 0.85, 'color': 'magenta'}}},\n", " 'plot_grp3a': {'type': 'spatial_overlay',\n", " 'fig_kwargs': {'states': True, 'figsize': [10, 5]},\n", " 'text_kwargs': {'fontsize': 16.0},\n", " 'domain_type': ['epa_region', 'siteid'],\n", " 'domain_name': ['R5', '260810020'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'data_proc': {'rem_obs_nan': True,\n", " 'set_axis': True,\n", " 'wind_barb': True,\n", " 'wind_barb_step': 2,\n", " 'filter_string': 'WS != 0 and WD != 0'}},\n", " 'plot_grp4': {'type': 'boxplot',\n", " 'fig_kwargs': {'figsize': [8, 6]},\n", " 'text_kwargs': {'fontsize': 20.0},\n", " 'domain_type': ['epa_region'],\n", " 'domain_name': ['R5'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'data_proc': {'rem_obs_nan': True,\n", " 'set_axis': False,\n", " 'set_stat_sig': False}},\n", " 'plot_grp5': {'type': 'multi_boxplot',\n", " 'fig_kwargs': {'figsize': [10, 8]},\n", " 'text_kwargs': {'fontsize': 20.0},\n", " 'gridlines': True,\n", " 'xlabel': 'Binned by Observed Wind Speed (m/s)',\n", " 'domain_type': ['epa_region'],\n", " 'domain_name': ['R5'],\n", " 'interval_list': [0, 3, 5, 8, 11, 14],\n", " 'interval_var': 'WS',\n", " 'interval_labels': ['[0, 3)', '[3, 5)', '[5, 8)', '[8, 11)', '[11, 14)'],\n", " 'model_name_list': ['AirNow', 'ufschem_v1'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': False}},\n", " 'plot_grp6': {'type': 'rose_plot',\n", " 'text_kwargs': {'fontsize': 16.0},\n", " 'domain_type': ['state_name', 'siteid'],\n", " 'domain_name': ['MI', '260810020'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'color_map': 'inferno',\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': True, 'wr_calm_limit': 0.5}},\n", " 'plot_grp7': {'type': 'diurnal',\n", " 'fig_kwargs': {'figsize': [12, 6]},\n", " 'default_plot_kwargs': {'linewidth': 2.0, 'markersize': 10.0},\n", " 'text_kwargs': {'fontsize': 24.0},\n", " 'domain_type': ['state_name', 'epa_region'],\n", " 'domain_name': ['MI', 'R5'],\n", " 'data': ['airnow_ufschem_v1'],\n", " 'data_proc': {'rem_obs_nan': True,\n", " 'ts_select_time': 'time_local',\n", " 'ts_avg_window': 'h',\n", " 'set_axis': True}}},\n", " 'stats': {'stat_list': ['MB', 'MdnB', 'R2', 'RMSE', 'MAE', 'MSE'],\n", " 'round_output': 2,\n", " 'output_table': True,\n", " 'output_table_kwargs': {'figsize': [7, 3],\n", " 'fontsize': 12.0,\n", " 'xscale': 1.4,\n", " 'yscale': 1.4,\n", " 'edges': 'horizontal'},\n", " 'domain_type': ['epa_region'],\n", " 'domain_name': ['R5'],\n", " 'data': ['airnow_ufschem_v1']}}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "an.control = \"control_ufschem-example.yaml\"\n", "an.read_control()\n", "an.control_dict" ] }, { "cell_type": "markdown", "id": "e1ee480a", "metadata": {}, "source": [ "````{admonition} Note: This is the complete file that was loaded.\n", ":class: dropdown\n", "\n", "```{literalinclude} control_wrfchem_mech-0905_2.yaml\n", ":caption:\n", ":linenos:\n", "```\n", "````\n", "\n", "Now, some of our {class}`~melodies_monet.driver.analysis` object's attributes are populated:" ] }, { "cell_type": "code", "execution_count": 5, "id": "66cff826", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "analysis(\n", " control='control_ufschem-example.yaml',\n", " control_dict=...,\n", " models={},\n", " obs={},\n", " paired={},\n", " start_time=Timestamp('2017-07-01 00:00:00'),\n", " end_time=Timestamp('2017-07-03 00:00:00'),\n", " time_intervals=None,\n", " download_maps=True,\n", " output_dir='./output/airnow_ufschem',\n", " output_dir_save='./output/airnow_ufschem',\n", " output_dir_read='./output/airnow_ufschem',\n", " debug=True,\n", " save=None,\n", " read=None,\n", " regrid=False,\n", ")" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "an" ] }, { "cell_type": "markdown", "id": "f6a98d98", "metadata": {}, "source": [ "## Load the model data\n", "\n", "The driver will automatically loop through the \"models\" found in the `model` section\n", "of the YAML file and create an instance of {class}`melodies_monet.driver.model` for each\n", "that includes the\n", "* label\n", "* mapping information\n", "* file names (can be expressed using a glob expression)\n", "* xarray object\n", "\n", "````{admonition} Note: Relevant control file section.\n", ":class: dropdown\n", "\n", "```{literalinclude} control_wrfchem_mech-0905_2.yaml\n", ":caption:\n", ":linenos:\n", ":lines: 24-56\n", "```\n", "````" ] }, { "cell_type": "code", "execution_count": 6, "id": "9a1ed373", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "ufs\n", "example:ufschem:2017-07\n", "**** Reading UFS-AQM or UFS-Chem model output...\n", "Performing extra model calculations...\n", "Calculating modeled relative humidity...\n", "Calculating modeled windspeed...\n", "Calculating modeled wind direction...\n" ] } ], "source": [ "an.open_models()" ] }, { "cell_type": "markdown", "id": "487d1357", "metadata": {}, "source": [ "Applying {meth}`~melodies_monet.driver.analysis.open_models`\n", "populates the {attr}`~melodies_monet.driver.analysis.models` attribute." ] }, { "cell_type": "raw", "id": "b4335da4-6d81-43c0-b9d3-57bdb34cc897", "metadata": {}, "source": [ "an.models" ] }, { "cell_type": "markdown", "id": "67fee521", "metadata": {}, "source": [ "We can access the underlying dataset with the\n", "{attr}`~melodies_monet.driver.model.obj` attribute." ] }, { "cell_type": "code", "execution_count": 7, "id": "c27a6f8e", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
<xarray.Dataset> Size: 320MB\n",
"Dimensions: (time: 72, z: 1, y: 192, x: 384)\n",
"Coordinates:\n",
" latitude (y, x) float64 590kB dask.array<chunksize=(192, 384), meta=np.ndarray>\n",
" longitude (y, x) float64 590kB dask.array<chunksize=(192, 384), meta=np.ndarray>\n",
" * time (time) datetime64[ns] 576B 2017-07-01T01:00:00 ... 2017-07-04\n",
" * x (x) float64 3kB 0.0 0.9375 1.875 2.812 ... 357.2 358.1 359.1\n",
" * y (y) float64 2kB 89.28 88.36 87.42 ... -87.42 -88.36 -89.28\n",
"Dimensions without coordinates: z\n",
"Data variables: (12/14)\n",
" o3 (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" temperature_k (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" surfpres_pa (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" dp_pa (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" surfalt_m (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" dz_m (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" ... ...\n",
" spfh2m (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" ugrd10m (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" vgrd10m (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" rel_hum (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" windspeed (time, z, y, x) float32 21MB dask.array<chunksize=(1, 1, 192, 384), meta=np.ndarray>\n",
" winddir (time, z, y, x) float32 21MB 243.3 244.2 ... 352.7 351.9\n",
"Attributes:\n",
" grid: gaussian\n",
" grid_id: 1\n",
" hydrostatic: non-hydrostatic\n",
" im: 384\n",
" jm: 192\n",
" ncnsto: 139\n",
" source: FV3GFS\n",
" NCO: netCDF Operators version 5.0.7 (Homepage = http://nco.sf.ne...\n",
" ak: [0. 0.]\n",
" bk: [0.99467119 1. ]\n",
" history: Fri Feb 27 09:53:22 2026: ncrcat 20170701_dynf001.nc 201707...<xarray.Dataset> Size: 18MB\n",
"Dimensions: (time: 49, y: 1, x: 1934)\n",
"Coordinates:\n",
" * time (time) datetime64[ns] 392B 2017-07-01 ... 2017-07-03\n",
" siteid (x) <U9 70kB ...\n",
" latitude (x) float64 15kB ...\n",
" longitude (x) float64 15kB ...\n",
" * x (x) int64 15kB 0 1 2 3 4 5 6 ... 1928 1929 1930 1931 1932 1933\n",
"Dimensions without coordinates: y\n",
"Data variables: (12/30)\n",
" BARPR (time, y, x) float64 758kB ...\n",
" BC (time, y, x) float64 758kB ...\n",
" CO (time, y, x) float64 758kB ...\n",
" NO (time, y, x) float64 758kB ...\n",
" NO2 (time, y, x) float64 758kB ...\n",
" NO2Y (time, y, x) float64 758kB ...\n",
" ... ...\n",
" utcoffset (y, x) int64 15kB ...\n",
" cmsa_name (y, x) float64 15kB ...\n",
" msa_code (y, x) float64 15kB ...\n",
" msa_name (y, x) <U52 402kB ...\n",
" state_name (y, x) <U2 15kB ...\n",
" epa_region (y, x) <U5 39kB ...