{ "cells": [ { "cell_type": "markdown", "id": "f9507824", "metadata": {}, "source": [ "# AirNow and WRF-Chem\n", "\n", "Our first example will demonstrate the basics available in MELODIES MONET to \n", "compare WRF-Chem model results against AirNow surface observations for\n", "ozone and PM{subscript}`2.5`.\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.\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-05-06:00:00',\n", " 'end_time': '2019-09-06-06:00:00',\n", " 'output_dir': './output/airnow_wrfchem',\n", " 'debug': True},\n", " 'model': {'RACM_ESRL': {'files': 'example:wrfchem:racm_esrl',\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',\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", " '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", " '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': 'h',\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_grp4': {'type': 'spatial_overlay',\n", " 'fig_kwargs': {'states': True, 'figsize': [10, 5]},\n", " 'text_kwargs': {'fontsize': 16.0},\n", " 'domain_type': ['all', 'epa_region'],\n", " 'domain_name': ['CONUS', 'R9'],\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_grp6': {'type': 'scorecard',\n", " 'fig_kwargs': {'figsize': [15, 10]},\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", " 'urban_rural_name': ['msa_name'],\n", " 'urban_rural_differentiate_value': '',\n", " 'better_or_worse_method': 'NME',\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_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', 'R1'],\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.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.yaml',\n", " control_dict=...,\n", " models={},\n", " obs={},\n", " paired={},\n", " start_time=Timestamp('2019-09-05 06:00:00'),\n", " end_time=Timestamp('2019-09-06 06:00:00'),\n", " time_intervals=None,\n", " download_maps=True,\n", " output_dir='./output/airnow_wrfchem',\n", " output_dir_save='./output/airnow_wrfchem',\n", " output_dir_read='./output/airnow_wrfchem',\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\n", "**** Reading WRF-Chem model output...\n", "wrfchem\n", "example:wrfchem:racm_esrl_vcp\n", "**** Reading WRF-Chem model output...\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "**** Reading WRF-Chem model output...\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "wrfchem\n", "example:wrfchem:racm_esrl_vcp\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "**** 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': ['o3', 'PM2_5_DRY']},\n", " file_str='example:wrfchem:racm_esrl',\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': ['o3', 'PM2_5_DRY']},\n", " file_str='example:wrfchem:racm_esrl_vcp',\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: 32MB\n",
"Dimensions: (y: 284, x: 440, time: 31, 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] 248B 2019-09-05 ... 2019-09-06T06:00:00\n",
"Dimensions without coordinates: y, x, z\n",
"Data variables:\n",
" o3 (time, z, y, x) float32 15MB 30.0 30.0 30.0 ... 34.72 36.87 37.13\n",
" PM2_5_DRY (time, z, y, x) float32 15MB 3.046 3.048 2.84 ... 0.4506 0.4512\n",
"Attributes: (12/17)\n",
" FieldType: 104\n",
" MemoryOrder: XYZ\n",
" description: O3 mixing ratio\n",
" units: ppmv\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':...<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