{ "cells": [ { "cell_type": "markdown", "id": "f9507824", "metadata": {}, "source": [ "# AirNow and WRF-Chem Regulatory Calculations\n", "\n", "This example will compare WRF-Chem model results against AirNow surface observations for the\n", "MDA8 ozone and 24 hour average PM{subscript}`2.5` regulatory metrics.\n", "\n", "```{note}\n", "Check out the {doc}`/users_guide/supported_diagnostics` for information on how MELODIES MONET calculates these regulatory metrics\n", "```\n", "\n", "All default surface plots are available for the regulatory calculations except for the ``spatial_overlay`` and ``scorecard`` plots. There is also an additional plot called the ``spatial_bias_exceedance`` plot available that is a difference plot of model - observations for the number of exceedances greater than the regulatory standard within the analysis window with options to specify the domain. \n", "\n", "```{note}\n", "Check out the {doc}`/users_guide/supported_plots` for more description of these plots.\n", "```\n", "\n", "This example shows how one can compare results from two different model simulations against observations. This particular example compares WRF-Chem results using two different chemical mechanisms (RACM_ESRL and RACM_ESRL_VCP). Simulated surface ozone is slightly improved in WRF-Chem using the RACM_ESRL_VCP mechanism as compared to the AirNow observations. \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. As shown below in order to calculate regulatory metrics set ``regulatory`` equal to ``True`` under each relevant observation. Currently, regulatory calculations are only available for ozone and PM{subscript}`2.5`.\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': '2019-09-04-06:00:00',\n", " 'end_time': '2019-09-06-05:00:00',\n", " 'output_dir': './output/airnow_wrfchem_reg',\n", " 'debug': True},\n", " 'model': {'RACM_ESRL': {'files': 'example:wrfchem:racm_esrl_reg',\n", " 'mod_type': 'wrfchem',\n", " 'mod_kwargs': {'mech': 'racm_esrl_vcp', 'surf_only_nc': True},\n", " 'radius_of_influence': 12000,\n", " 'mapping': {'airnow': {'PM2_5_DRY': 'PM2.5', 'o3': 'OZONE'}},\n", " 'projection': None,\n", " 'plot_kwargs': {'color': 'magenta', 'marker': 's', 'linestyle': '-'}},\n", " 'RACM_ESRL_VCP': {'files': 'example:wrfchem:racm_esrl_vcp_reg',\n", " 'mod_type': 'wrfchem',\n", " 'mod_kwargs': {'mech': 'racm_esrl_vcp', 'surf_only_nc': True},\n", " 'radius_of_influence': 12000,\n", " 'mapping': {'airnow': {'PM2_5_DRY': 'PM2.5', 'o3': 'OZONE'}},\n", " 'projection': None,\n", " 'plot_kwargs': {'color': 'gold', 'marker': 'o', 'linestyle': '-'}}},\n", " 'obs': {'airnow': {'use_airnow': True,\n", " 'filename': 'example:airnow:2019-09',\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", " 'vmin_plot': 15.0,\n", " 'vmax_plot': 55.0,\n", " 'vdiff_plot': 20.0,\n", " 'nlevels_plot': 21,\n", " 'regulatory': True,\n", " 'ylabel_reg_plot': 'MDA8 O3 (ppbv)',\n", " 'vmin_reg_plot': 30.0,\n", " 'vmax_reg_plot': 70.0,\n", " 'vdiff_reg_plot': 20.0},\n", " 'PM2.5': {'unit_scale': 1,\n", " 'unit_scale_method': '*',\n", " 'nan_value': -1.0,\n", " 'ylabel_plot': 'PM2.5 (ug/m3)',\n", " 'ty_scale': 2.0,\n", " 'vmin_plot': 0.0,\n", " 'vmax_plot': 22.0,\n", " 'vdiff_plot': 15.0,\n", " 'nlevels_plot': 23,\n", " 'regulatory': True,\n", " 'ylabel_reg_plot': 'PM2.5_24hr (ug/m3)',\n", " 'vmin_reg_plot': 0.0,\n", " 'vmax_reg_plot': 22.0,\n", " 'vdiff_reg_plot': 15.0}}}},\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': ['all', 'state_name', 'epa_region'],\n", " 'domain_name': ['CONUS', 'CA', 'R9'],\n", " 'data': ['airnow_RACM_ESRL', 'airnow_RACM_ESRL_VCP'],\n", " 'data_proc': {'rem_obs_nan': True,\n", " 'ts_select_time': 'time_local',\n", " 'ts_avg_window': 'D',\n", " 'set_axis': True}},\n", " 'plot_grp2': {'type': 'taylor',\n", " 'fig_kwargs': {'figsize': [8, 8]},\n", " 'default_plot_kwargs': {'linewidth': 2.0, 'markersize': 10.0},\n", " 'text_kwargs': {'fontsize': 16.0},\n", " 'domain_type': ['all'],\n", " 'domain_name': ['CONUS'],\n", " 'data': ['airnow_RACM_ESRL', 'airnow_RACM_ESRL_VCP'],\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': True}},\n", " 'plot_grp3': {'type': 'spatial_bias',\n", " 'fig_kwargs': {'states': True, 'figsize': [10, 5]},\n", " 'text_kwargs': {'fontsize': 16.0},\n", " 'domain_type': ['all'],\n", " 'domain_name': ['CONUS'],\n", " 'data': ['airnow_RACM_ESRL', 'airnow_RACM_ESRL_VCP'],\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': True}},\n", " 'plot_grp5': {'type': 'boxplot',\n", " 'fig_kwargs': {'figsize': [8, 6]},\n", " 'text_kwargs': {'fontsize': 20.0},\n", " 'domain_type': ['all'],\n", " 'domain_name': ['CONUS'],\n", " 'data': ['airnow_RACM_ESRL', 'airnow_RACM_ESRL_VCP'],\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': False}},\n", " 'plot_grp5_5': {'type': 'spatial_bias_exceedance',\n", " 'fig_kwargs': {'states': True, 'figsize': [10, 5]},\n", " 'text_kwargs': {'fontsize': 16.0},\n", " 'domain_type': ['all'],\n", " 'domain_name': ['CONUS'],\n", " 'data': ['airnow_RACM_ESRL', 'airnow_RACM_ESRL_VCP'],\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': False}},\n", " 'plot_grp7': {'type': 'multi_boxplot',\n", " 'fig_kwargs': {'figsize': [10, 8]},\n", " 'text_kwargs': {'fontsize': 20.0},\n", " 'domain_type': ['all'],\n", " 'domain_name': ['CONUS'],\n", " 'region_name': ['epa_region'],\n", " 'region_list': ['R1',\n", " 'R2',\n", " 'R3',\n", " 'R4',\n", " 'R5',\n", " 'R6',\n", " 'R7',\n", " 'R8',\n", " 'R9',\n", " 'R10'],\n", " 'model_name_list': ['AirNow', 'RACM_ESRL', 'RACM_ESRL_VCP'],\n", " 'data': ['airnow_RACM_ESRL', 'airnow_RACM_ESRL_VCP'],\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': False}},\n", " 'plot_grp8': {'type': 'csi',\n", " 'fig_kwargs': {'figsize': [10, 8]},\n", " 'text_kwargs': {'fontsize': 20.0},\n", " 'domain_type': ['all', 'epa_region'],\n", " 'domain_name': ['CONUS', 'R9'],\n", " 'threshold_list': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100],\n", " 'score_name': 'Critical Success Index',\n", " 'model_name_list': ['RACM_ESRL', 'RACM_ESRL_VCP'],\n", " 'data': ['airnow_RACM_ESRL', 'airnow_RACM_ESRL_VCP'],\n", " 'data_proc': {'rem_obs_nan': True, 'set_axis': False}}},\n", " 'stats': {'stat_list': ['MB', 'MdnB', 'R2', 'RMSE'],\n", " 'round_output': 2,\n", " 'output_table': False,\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': ['all'],\n", " 'domain_name': ['CONUS'],\n", " 'data': ['airnow_RACM_ESRL', 'airnow_RACM_ESRL_VCP']}}" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "an.control = \"control_wrfchem_mech-0905_2_reg.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_wrfchem_mech-0905_2_reg.yaml',\n", " control_dict=...,\n", " models={},\n", " obs={},\n", " paired={},\n", " start_time=Timestamp('2019-09-04 06:00:00'),\n", " end_time=Timestamp('2019-09-06 05:00:00'),\n", " time_intervals=None,\n", " download_maps=True,\n", " output_dir='./output/airnow_wrfchem_reg',\n", " output_dir_save='./output/airnow_wrfchem_reg',\n", " output_dir_read='./output/airnow_wrfchem_reg',\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": [ "wrfchem\n", "example:wrfchem:racm_esrl_reg\n", "**** Reading WRF-Chem model output...\n", "wrfchem\n", "example:wrfchem:racm_esrl_vcp_reg\n", "**** Reading WRF-Chem model output...\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": "code", "execution_count": 7, "id": "18e908f6", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'RACM_ESRL': model(\n", " model='wrfchem',\n", " is_global=False,\n", " radius_of_influence=12000,\n", " mod_kwargs={'mech': 'racm_esrl_vcp', 'surf_only_nc': True, 'var_list': ['PM2_5_DRY', 'o3']},\n", " file_str='example:wrfchem:racm_esrl_reg',\n", " label='RACM_ESRL',\n", " obj=...,\n", " mapping={'airnow': {'PM2_5_DRY': 'PM2.5', 'o3': 'OZONE'}},\n", " variable_dict=None,\n", " label='RACM_ESRL',\n", " ...\n", " ),\n", " 'RACM_ESRL_VCP': model(\n", " model='wrfchem',\n", " is_global=False,\n", " radius_of_influence=12000,\n", " mod_kwargs={'mech': 'racm_esrl_vcp', 'surf_only_nc': True, 'var_list': ['PM2_5_DRY', 'o3']},\n", " file_str='example:wrfchem:racm_esrl_vcp_reg',\n", " label='RACM_ESRL_VCP',\n", " obj=...,\n", " mapping={'airnow': {'PM2_5_DRY': 'PM2.5', 'o3': 'OZONE'}},\n", " variable_dict=None,\n", " label='RACM_ESRL_VCP',\n", " ...\n", " )}" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "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": 8, "id": "c27a6f8e", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
<xarray.Dataset> Size: 49MB\n",
"Dimensions: (y: 284, x: 440, time: 48, z: 1)\n",
"Coordinates:\n",
" longitude (y, x) float32 500kB -122.3 -122.2 -122.1 ... -60.52 -60.37\n",
" latitude (y, x) float32 500kB 21.19 21.22 21.24 21.27 ... 50.28 50.24 50.2\n",
" * time (time) datetime64[ns] 384B 2019-09-04T06:00:00 ... 2019-09-06T...\n",
"Dimensions without coordinates: y, x, z\n",
"Data variables:\n",
" PM2_5_DRY (time, z, y, x) float32 24MB 1.916 1.911 1.895 ... 0.4702 0.4709\n",
" o3 (time, z, y, x) float32 24MB 32.62 32.62 32.6 ... 37.28 37.56\n",
"Attributes: (12/15)\n",
" FieldType: 104\n",
" MemoryOrder: XYZ\n",
" description: pm2.5 aerosol dry mass\n",
" units: ug m^-3\n",
" stagger: \n",
" coordinates: XLONG XLAT XTIME\n",
" ... ...\n",
" MOAD_CEN_LAT: 39.617638\n",
" STAND_LON: -97.0\n",
" MAP_PROJ: 1\n",
" CEN_LAT: 39.617638\n",
" CEN_LON: -97.77487\n",
" mapping_tables_to_airnow: {'OZONE': 'o3', 'PM2.5': 'PM2_5_DRY', 'PM10': ...<xarray.Dataset> Size: 1GB\n",
"Dimensions: (x: 3786, time: 2091, y: 1)\n",
"Coordinates:\n",
" * x (x) int64 30kB 0 1 2 3 4 5 6 ... 3780 3781 3782 3783 3784 3785\n",
" * time (time) datetime64[ns] 17kB 2019-09-01 ... 2019-09-30T00:30:00\n",
" latitude (y, x) float64 30kB ...\n",
" longitude (y, x) float64 30kB ...\n",
" siteid (y, x) <U12 182kB ...\n",
"Dimensions without coordinates: y\n",
"Data variables: (12/30)\n",
" BARPR (time, y, x) float64 63MB ...\n",
" BC (time, y, x) float64 63MB ...\n",
" CO (time, y, x) float64 63MB ...\n",
" NO (time, y, x) float64 63MB ...\n",
" NO2 (time, y, x) float64 63MB ...\n",
" NO2Y (time, y, x) float64 63MB ...\n",
" ... ...\n",
" cmsa_name (y, x) float64 30kB ...\n",
" msa_code (y, x) float64 30kB ...\n",
" msa_name (y, x) <U52 787kB ...\n",
" state_name (y, x) <U2 30kB ...\n",
" epa_region (y, x) <U5 76kB ...\n",
" time_local (time, y, x) datetime64[ns] 63MB ...\n",
"Attributes:\n",
" title: \n",
" format: NetCDF-4\n",
" date_created: 2021-06-07