Inspect data¶
In [1]:
Copied!
import logging
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from ghg_forcing_for_cmip import download_ground_based, download_satellite, plotting
from ghg_forcing_for_cmip.validation import compute_discrepancy_collocated
# silent prefect run
logging.getLogger("prefect").setLevel(logging.ERROR)
# run pipeline to download data
for gas in ["co2", "ch4"]:
download_ground_based.download_surface_data(gas=gas, remove_original_files=False)
download_satellite.download_satellite_data(gas=gas, remove_original_files=False)
import logging
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from ghg_forcing_for_cmip import download_ground_based, download_satellite, plotting
from ghg_forcing_for_cmip.validation import compute_discrepancy_collocated
# silent prefect run
logging.getLogger("prefect").setLevel(logging.ERROR)
# run pipeline to download data
for gas in ["co2", "ch4"]:
download_ground_based.download_surface_data(gas=gas, remove_original_files=False)
download_satellite.download_satellite_data(gas=gas, remove_original_files=False)
/home/docs/checkouts/readthedocs.org/user_builds/ghg-forcing-for-cmip/envs/latest/lib/python3.11/site-packages/pydantic_settings/main.py:426: UserWarning: Config key `pyproject_toml_table_header` is set in model_config but will be ignored because no PyprojectTomlConfigSettingsSource source is configured. To use this config key, add a PyprojectTomlConfigSettingsSource source to the settings sources via the settings_customise_sources hook. self._settings_warn_unused_config_keys(sources, self.model_config) /home/docs/checkouts/readthedocs.org/user_builds/ghg-forcing-for-cmip/envs/latest/lib/python3.11/site-packages/pydantic_settings/main.py:426: UserWarning: Config key `toml_file` is set in model_config but will be ignored because no TomlConfigSettingsSource source is configured. To use this config key, add a TomlConfigSettingsSource source to the settings sources via the settings_customise_sources hook. self._settings_warn_unused_config_keys(sources, self.model_config)
/home/docs/checkouts/readthedocs.org/user_builds/ghg-forcing-for-cmip/envs/latest/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py:2249: UnsupportedFieldAttributeWarning: The 'default' attribute with value 'UTC' was provided to the `Field()` function, which has no effect in the context it was used. 'default' is field-specific metadata, and can only be attached to a model field using `Annotated` metadata or by assignment. This may have happened because an `Annotated` type alias using the `type` statement was used, or if the `Field()` function was attached to a single member of a union type. warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/ghg-forcing-for-cmip/envs/latest/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py:2249: UnsupportedFieldAttributeWarning: The 'default' attribute with value 'UTC' was provided to the `Field()` function, which has no effect in the context it was used. 'default' is field-specific metadata, and can only be attached to a model field using `Annotated` metadata or by assignment. This may have happened because an `Annotated` type alias using the `type` statement was used, or if the `Field()` function was attached to a single member of a union type. warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/ghg-forcing-for-cmip/envs/latest/lib/python3.11/site-packages/pydantic_settings/main.py:426: UserWarning: Config key `pyproject_toml_table_header` is set in model_config but will be ignored because no PyprojectTomlConfigSettingsSource source is configured. To use this config key, add a PyprojectTomlConfigSettingsSource source to the settings sources via the settings_customise_sources hook. self._settings_warn_unused_config_keys(sources, self.model_config) /home/docs/checkouts/readthedocs.org/user_builds/ghg-forcing-for-cmip/envs/latest/lib/python3.11/site-packages/pydantic_settings/main.py:426: UserWarning: Config key `toml_file` is set in model_config but will be ignored because no TomlConfigSettingsSource source is configured. To use this config key, add a TomlConfigSettingsSource source to the settings sources via the settings_customise_sources hook. self._settings_warn_unused_config_keys(sources, self.model_config)
In [2]:
Copied!
d_gb_ch4 = pd.read_csv("data/downloads/ch4/ch4_gb_raw.csv")
d_gb_co2 = pd.read_csv("data/downloads/co2/co2_gb_raw.csv")
d_gb_ch4.head()
d_gb_ch4 = pd.read_csv("data/downloads/ch4/ch4_gb_raw.csv")
d_gb_co2 = pd.read_csv("data/downloads/co2/co2_gb_raw.csv")
d_gb_ch4.head()
Out[2]:
| year | month | latitude | longitude | altitude | value | std_dev | numb | site_code | network | ... | unit | version | instrument | lat | lon | bnd | lat_bnd | lon_bnd | time_fractional | time | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1983 | 1 | -75.604202 | -26.601500 | 13.0 | 1560.179199 | 2.809700 | 216 | HBA | noaa | ... | ppb | 2025-08-15T13:48:06.496334 | noaa | -77.5 | -27.5 | 0 | -75 | -25 | 1983.083333 | 1983-01-15 12:00:00+00:00 |
| 1 | 1983 | 1 | -75.604202 | -26.601500 | 13.0 | 1560.179199 | 2.809700 | 216 | HBA | noaa | ... | ppb | 2025-08-15T13:48:06.496334 | noaa | -77.5 | -27.5 | 1 | -80 | -30 | 1983.083333 | 1983-01-15 12:00:00+00:00 |
| 2 | 1983 | 1 | -64.774200 | -64.052696 | 13.0 | 1557.342407 | 8.102857 | 180 | PSA | noaa | ... | ppb | 2025-08-15T13:48:06.496334 | noaa | -62.5 | -62.5 | 0 | -60 | -60 | 1983.083333 | 1983-01-15 12:00:00+00:00 |
| 3 | 1983 | 1 | -64.774200 | -64.052696 | 13.0 | 1557.342407 | 8.102857 | 180 | PSA | noaa | ... | ppb | 2025-08-15T13:48:06.496334 | noaa | -62.5 | -62.5 | 1 | -65 | -65 | 1983.083333 | 1983-01-15 12:00:00+00:00 |
| 4 | 1983 | 1 | -37.950001 | 77.529999 | 153.0 | 1558.405273 | 10.514277 | 144 | AMS | noaa | ... | ppb | 2025-08-15T13:48:06.496334 | noaa | -37.5 | 77.5 | 0 | -35 | 75 | 1983.083333 | 1983-01-15 12:00:00+00:00 |
5 rows × 23 columns
In [3]:
Copied!
d_eo_ch4 = pd.read_csv("data/downloads/ch4/ch4_eo_raw.csv")
d_eo_co2 = pd.read_csv("data/downloads/co2/co2_eo_raw.csv")
d_eo_ch4.head()
d_eo_ch4 = pd.read_csv("data/downloads/ch4/ch4_eo_raw.csv")
d_eo_co2 = pd.read_csv("data/downloads/co2/co2_eo_raw.csv")
d_eo_ch4.head()
Out[3]:
| time | year | month | lat_bnd | lon_bnd | bnd | lat | lon | value | std_dev | numb | gas | unit | pre | column_averaging_kernel | vmr_profile_apriori | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2003-01-16 12:00:00+00:00 | 2003 | 1 | -85 | -120 | 0 | -82.5 | -117.5 | 1611.184302 | 47.167322 | 17 | ch4 | ppb | 0.95 | 1.188702 | 1714.261884 |
| 1 | 2003-01-16 12:00:00+00:00 | 2003 | 1 | -85 | -120 | 0 | -82.5 | -117.5 | 1611.184302 | 47.167322 | 17 | ch4 | ppb | 0.85 | 1.156435 | 1713.341703 |
| 2 | 2003-01-16 12:00:00+00:00 | 2003 | 1 | -85 | -120 | 0 | -82.5 | -117.5 | 1611.184302 | 47.167322 | 17 | ch4 | ppb | 0.75 | 1.115912 | 1712.569428 |
| 3 | 2003-01-16 12:00:00+00:00 | 2003 | 1 | -85 | -120 | 0 | -82.5 | -117.5 | 1611.184302 | 47.167322 | 17 | ch4 | ppb | 0.65 | 1.073409 | 1712.066933 |
| 4 | 2003-01-16 12:00:00+00:00 | 2003 | 1 | -85 | -120 | 0 | -82.5 | -117.5 | 1611.184302 | 47.167322 | 17 | ch4 | ppb | 0.55 | 1.017909 | 1711.855703 |
In [4]:
Copied!
_, axs = plt.subplots(1, 2, constrained_layout=True, figsize=(11, 6))
plotting.plot_map(
d_gb_ch4,
# Don't need the +, just put the strings in brackets and
# they're automatically joined
(
f"Observations sites ({d_gb_ch4.year.min()}-{d_gb_ch4.year.max()})"
"\n $CH_4$ data"
),
axs[0],
)
plotting.plot_map(
d_gb_co2,
(
f"Observations sites ({d_gb_co2.year.min()}-{d_gb_co2.year.max()})"
"\n $CO_2$ data"
),
axs[1],
)
_, axs = plt.subplots(1, 2, constrained_layout=True, figsize=(11, 6))
plotting.plot_map(
d_gb_ch4,
# Don't need the +, just put the strings in brackets and
# they're automatically joined
(
f"Observations sites ({d_gb_ch4.year.min()}-{d_gb_ch4.year.max()})"
"\n $CH_4$ data"
),
axs[0],
)
plotting.plot_map(
d_gb_co2,
(
f"Observations sites ({d_gb_co2.year.min()}-{d_gb_co2.year.max()})"
"\n $CO_2$ data"
),
axs[1],
)
Downloading file 'ne_110m_land.zip' from 'https://naciscdn.org/naturalearth/110m/physical/ne_110m_land.zip' to '/home/docs/.cache/geodatasets'.
Out[4]:
<Axes: title={'center': 'Observations sites (1968-2024)\n $CO_2$ data'}>
In [5]:
Copied!
_, axs = plt.subplots(2, 3, constrained_layout=True, figsize=(9, 3))
# Zip plus `.flatten` lets you avoid this enumerate thinking
# and double loop
for ax, year in zip(axs.flatten(), [2003, 2008, 2013, 2018, 2020, 2022]):
plotting.plot_map(
d_eo_ch4[d_eo_ch4.year == year],
f"OBS4MIPs ({year}), $CH_4$ data",
ax,
"lon",
"lat",
".",
5,
)
_, axs = plt.subplots(2, 3, constrained_layout=True, figsize=(9, 3))
# Zip plus `.flatten` lets you avoid this enumerate thinking
# and double loop
for ax, year in zip(axs.flatten(), [2003, 2008, 2013, 2018, 2020, 2022]):
plotting.plot_map(
d_eo_ch4[d_eo_ch4.year == year],
f"OBS4MIPs ({year}), $CH_4$ data",
ax,
"lon",
"lat",
".",
5,
)
Carbon Dioxide¶
In [6]:
Copied!
_, axs = plt.subplots(2, 3, constrained_layout=True, figsize=(9, 3))
# Zip plus `.flatten` lets you avoid this enumerate thinking
# and double loop
for ax, year in zip(axs.flatten(), [2003, 2008, 2013, 2018, 2020, 2022]):
plotting.plot_map(
d_eo_co2[d_eo_co2.year == year],
f"OBS4MIPs ({year}), $CO_2$ data",
ax,
"lon",
"lat",
".",
5,
)
_, axs = plt.subplots(2, 3, constrained_layout=True, figsize=(9, 3))
# Zip plus `.flatten` lets you avoid this enumerate thinking
# and double loop
for ax, year in zip(axs.flatten(), [2003, 2008, 2013, 2018, 2020, 2022]):
plotting.plot_map(
d_eo_co2[d_eo_co2.year == year],
f"OBS4MIPs ({year}), $CO_2$ data",
ax,
"lon",
"lat",
".",
5,
)
Comparison of raw ground-based data with satellite product¶
In [7]:
Copied!
# select collocated sites
d_gb_ch4_sel = d_gb_ch4[
["year", "month", "lat", "lon", "value", "site_code"]
].drop_duplicates()
d_eo_ch4_sel = d_eo_ch4[
["year", "month", "lat", "lon", "value", "pre", "vmr_profile_apriori"]
].drop_duplicates()
d_gb_co2_sel = d_gb_co2[
["year", "month", "lat", "lon", "value", "site_code"]
].drop_duplicates()
d_eo_co2_sel = d_eo_co2[
["year", "month", "lat", "lon", "value", "pre", "vmr_profile_apriori"]
].drop_duplicates()
d_colloc_ch4 = d_gb_ch4_sel.merge(
d_eo_ch4_sel,
on=["year", "month", "lat", "lon"],
how="inner",
suffixes=["_gb", "_eo"],
)
d_colloc_co2 = d_gb_co2_sel.merge(
d_eo_co2_sel,
on=["year", "month", "lat", "lon"],
how="inner",
suffixes=["_gb", "_eo"],
)
d_colloc_ch4.to_csv("data/downloads/ch4/ch4_collocated.csv")
d_colloc_co2.to_csv("data/downloads/co2/co2_collocated.csv")
d_colloc_ch4.head()
# select collocated sites
d_gb_ch4_sel = d_gb_ch4[
["year", "month", "lat", "lon", "value", "site_code"]
].drop_duplicates()
d_eo_ch4_sel = d_eo_ch4[
["year", "month", "lat", "lon", "value", "pre", "vmr_profile_apriori"]
].drop_duplicates()
d_gb_co2_sel = d_gb_co2[
["year", "month", "lat", "lon", "value", "site_code"]
].drop_duplicates()
d_eo_co2_sel = d_eo_co2[
["year", "month", "lat", "lon", "value", "pre", "vmr_profile_apriori"]
].drop_duplicates()
d_colloc_ch4 = d_gb_ch4_sel.merge(
d_eo_ch4_sel,
on=["year", "month", "lat", "lon"],
how="inner",
suffixes=["_gb", "_eo"],
)
d_colloc_co2 = d_gb_co2_sel.merge(
d_eo_co2_sel,
on=["year", "month", "lat", "lon"],
how="inner",
suffixes=["_gb", "_eo"],
)
d_colloc_ch4.to_csv("data/downloads/ch4/ch4_collocated.csv")
d_colloc_co2.to_csv("data/downloads/co2/co2_collocated.csv")
d_colloc_ch4.head()
Out[7]:
| year | month | lat | lon | value_gb | site_code | value_eo | pre | vmr_profile_apriori | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 2003 | 1 | -52.5 | -67.5 | 1722.262451 | USH | 1631.436021 | 0.95 | 1725.226070 |
| 1 | 2003 | 1 | -52.5 | -67.5 | 1722.262451 | USH | 1631.436021 | 0.85 | 1720.670639 |
| 2 | 2003 | 1 | -52.5 | -67.5 | 1722.262451 | USH | 1631.436021 | 0.75 | 1717.441933 |
| 3 | 2003 | 1 | -52.5 | -67.5 | 1722.262451 | USH | 1631.436021 | 0.65 | 1715.137159 |
| 4 | 2003 | 1 | -52.5 | -67.5 | 1722.262451 | USH | 1631.436021 | 0.55 | 1714.451287 |
In [8]:
Copied!
fig, axs = plt.subplots(1, 2, figsize=(11, 3), constrained_layout=True)
plotting.plot_monthly_average(d_colloc_ch4, "$CH_4$", axs[0])
plotting.plot_monthly_average(d_colloc_co2, "$CO_2$", axs[1])
fig.suptitle("Annual, global average of GHG concentration")
fig, axs = plt.subplots(1, 2, figsize=(11, 3), constrained_layout=True)
plotting.plot_monthly_average(d_colloc_ch4, "$CH_4$", axs[0])
plotting.plot_monthly_average(d_colloc_co2, "$CO_2$", axs[1])
fig.suptitle("Annual, global average of GHG concentration")
Out[8]:
Text(0.5, 0.98, 'Annual, global average of GHG concentration')
In [9]:
Copied!
plotting.plot_average_hemisphere(d_colloc_ch4, "$CH_4$")
plotting.plot_average_hemisphere(d_colloc_ch4, "$CH_4$")
In [10]:
Copied!
plotting.plot_average_hemisphere(d_colloc_co2, "$CO_2$")
plotting.plot_average_hemisphere(d_colloc_co2, "$CO_2$")
In [11]:
Copied!
d_col_sorted_co2 = (
d_colloc_co2.groupby(["lat", "lon", "site_code"])
.agg({"value_gb": "count"})
.reset_index()
.sort_values(by="value_gb", ascending=False)
)
d_col_sorted_ch4 = (
d_colloc_ch4.groupby(["lat", "lon", "site_code"])
.agg({"value_gb": "count"})
.reset_index()
.sort_values(by="value_gb", ascending=False)
)
d_col_sorted_ch4.rename(columns={"value_gb": "count"}).head(10)
d_col_sorted_co2 = (
d_colloc_co2.groupby(["lat", "lon", "site_code"])
.agg({"value_gb": "count"})
.reset_index()
.sort_values(by="value_gb", ascending=False)
)
d_col_sorted_ch4 = (
d_colloc_ch4.groupby(["lat", "lon", "site_code"])
.agg({"value_gb": "count"})
.reset_index()
.sort_values(by="value_gb", ascending=False)
)
d_col_sorted_ch4.rename(columns={"value_gb": "count"}).head(10)
Out[11]:
| lat | lon | site_code | count | |
|---|---|---|---|---|
| 148 | 17.5 | -157.5 | MLO | 3640 |
| 60 | -12.5 | -172.5 | SMO | 2960 |
| 209 | 37.5 | 102.5 | WLG | 2500 |
| 206 | 37.5 | -97.5 | SGP | 2400 |
| 205 | 37.5 | -112.5 | UTA | 2280 |
| 215 | 42.5 | -107.5 | NWR | 2250 |
| 173 | 22.5 | 7.5 | ASK | 2220 |
| 220 | 42.5 | 112.5 | UUM | 2060 |
| 211 | 37.5 | 127.5 | TAP | 1940 |
| 225 | 47.5 | 17.5 | HUN | 1870 |
In [12]:
Copied!
max_lat = -50.0
d_col_sorted_co2[d_col_sorted_co2["lat"] <= max_lat].rename(
columns={"value_gb": "count"}
).head(2)
max_lat = -50.0
d_col_sorted_co2[d_col_sorted_co2["lat"] <= max_lat].rename(
columns={"value_gb": "count"}
).head(2)
Out[12]:
| lat | lon | site_code | count | |
|---|---|---|---|---|
| 5 | -52.5 | -67.5 | USH | 460 |
| 2 | -57.5 | -62.5 | DRP | 210 |
In [13]:
Copied!
min_lat = 50.0
d_col_sorted_co2[d_col_sorted_co2["lat"] >= max_lat].rename(
columns={"value_gb": "count"}
).head(2)
min_lat = 50.0
d_col_sorted_co2[d_col_sorted_co2["lat"] >= max_lat].rename(
columns={"value_gb": "count"}
).head(2)
Out[13]:
| lat | lon | site_code | count | |
|---|---|---|---|---|
| 43 | -12.5 | -172.5 | SMO | 3070 |
| 103 | 17.5 | -157.5 | MLO | 2690 |
In [14]:
Copied!
sites_selected_co2 = [
"SMO",
"MLO",
"USH",
"OXK",
]
sites_selected_ch4 = [
"SMO",
"MLO",
"USH",
"BRW",
]
sel_co2 = d_col_sorted_co2[d_col_sorted_co2.site_code.isin(sites_selected_co2)]
sel_ch4 = d_col_sorted_ch4[d_col_sorted_ch4.site_code.isin(sites_selected_ch4)]
_, axs = plt.subplots(1, 2, constrained_layout=True, figsize=(8, 5))
ax1 = plotting.plot_map(
sel_co2,
"Selected sites - CO2",
lon_value="lon",
lat_value="lat",
axs=axs[0],
)
ax2 = plotting.plot_map(
sel_ch4,
"Selected sites - CH4",
lon_value="lon",
lat_value="lat",
axs=axs[1],
)
for d, ax in zip([sel_co2, sel_ch4], [ax1, ax2]):
for lat, lon, label in zip(d.lat, d.lon, d.site_code):
ax.text(
lon + 15,
lat + 5,
label,
fontsize=8,
fontweight="bold",
ha="right",
va="bottom",
color="black",
)
sites_selected_co2 = [
"SMO",
"MLO",
"USH",
"OXK",
]
sites_selected_ch4 = [
"SMO",
"MLO",
"USH",
"BRW",
]
sel_co2 = d_col_sorted_co2[d_col_sorted_co2.site_code.isin(sites_selected_co2)]
sel_ch4 = d_col_sorted_ch4[d_col_sorted_ch4.site_code.isin(sites_selected_ch4)]
_, axs = plt.subplots(1, 2, constrained_layout=True, figsize=(8, 5))
ax1 = plotting.plot_map(
sel_co2,
"Selected sites - CO2",
lon_value="lon",
lat_value="lat",
axs=axs[0],
)
ax2 = plotting.plot_map(
sel_ch4,
"Selected sites - CH4",
lon_value="lon",
lat_value="lat",
axs=axs[1],
)
for d, ax in zip([sel_co2, sel_ch4], [ax1, ax2]):
for lat, lon, label in zip(d.lat, d.lon, d.site_code):
ax.text(
lon + 15,
lat + 5,
label,
fontsize=8,
fontweight="bold",
ha="right",
va="bottom",
color="black",
)
In [15]:
Copied!
d_col_sel_co2 = d_colloc_co2[
d_colloc_co2.site_code.isin(sites_selected_co2)
].reset_index(drop=True)
d_col_sel_ch4 = d_colloc_ch4[
d_colloc_ch4.site_code.isin(sites_selected_ch4)
].reset_index(drop=True)
d_col_sel_co2.to_csv("data/downloads/co2/co2_collocated_sites.csv")
d_col_sel_ch4.to_csv("data/downloads/ch4/ch4_collocated_sites.csv")
d_col_sel_co2 = d_colloc_co2[
d_colloc_co2.site_code.isin(sites_selected_co2)
].reset_index(drop=True)
d_col_sel_ch4 = d_colloc_ch4[
d_colloc_ch4.site_code.isin(sites_selected_ch4)
].reset_index(drop=True)
d_col_sel_co2.to_csv("data/downloads/co2/co2_collocated_sites.csv")
d_col_sel_ch4.to_csv("data/downloads/ch4/ch4_collocated_sites.csv")
In [16]:
Copied!
fig, axs = plt.subplots(2, 4, figsize=(11, 4), constrained_layout=True)
# Same zip trick as above
for site, ax in zip(sites_selected_co2, axs[0, :]):
d = d_col_sel_co2[d_col_sel_co2.site_code == site].copy()
rmse_co2 = compute_discrepancy_collocated(d, "co2", "rmse")
ax = plotting.plot_monthly_average(d, "$CO_2$", ax) # noqa: PLW2901
ax.set_title(
# As above re ability to use brackets instead of +
# (although this is really very optional
# and probably more a style choice than there being a right answer)
site
+ f", RMSE: {rmse_co2['rmse_co2'].values[0]:.2f},"
+ f"\nBias: {rmse_co2['bias_co2'].values[0]:.2f}, "
+ f"SD: {np.sqrt(rmse_co2['var_co2'].values[0]):.2f}",
fontsize="small",
)
ax.legend(fontsize="x-small", handlelength=0.4, frameon=False)
# zip could be used here too
for i, site in enumerate(sites_selected_ch4):
d = d_col_sel_ch4[d_col_sel_ch4.site_code == site].copy()
rmse_ch4 = compute_discrepancy_collocated(d, "ch4", "rmse")
axs[1, i] = plotting.plot_monthly_average(d, "$CH_4$", axs[1, i])
axs[1, i].set_title(
site
+ f", RMSE: {rmse_ch4['rmse_ch4'].values[0]:.2f},"
+ f"\nBias: {rmse_ch4['bias_ch4'].values[0]:.2f}, "
+ f"SD: {np.sqrt(rmse_ch4['var_ch4'].values[0]):.2f}",
fontsize="small",
)
axs[1, i].legend(fontsize="x-small", handlelength=0.4, frameon=False)
fig, axs = plt.subplots(2, 4, figsize=(11, 4), constrained_layout=True)
# Same zip trick as above
for site, ax in zip(sites_selected_co2, axs[0, :]):
d = d_col_sel_co2[d_col_sel_co2.site_code == site].copy()
rmse_co2 = compute_discrepancy_collocated(d, "co2", "rmse")
ax = plotting.plot_monthly_average(d, "$CO_2$", ax) # noqa: PLW2901
ax.set_title(
# As above re ability to use brackets instead of +
# (although this is really very optional
# and probably more a style choice than there being a right answer)
site
+ f", RMSE: {rmse_co2['rmse_co2'].values[0]:.2f},"
+ f"\nBias: {rmse_co2['bias_co2'].values[0]:.2f}, "
+ f"SD: {np.sqrt(rmse_co2['var_co2'].values[0]):.2f}",
fontsize="small",
)
ax.legend(fontsize="x-small", handlelength=0.4, frameon=False)
# zip could be used here too
for i, site in enumerate(sites_selected_ch4):
d = d_col_sel_ch4[d_col_sel_ch4.site_code == site].copy()
rmse_ch4 = compute_discrepancy_collocated(d, "ch4", "rmse")
axs[1, i] = plotting.plot_monthly_average(d, "$CH_4$", axs[1, i])
axs[1, i].set_title(
site
+ f", RMSE: {rmse_ch4['rmse_ch4'].values[0]:.2f},"
+ f"\nBias: {rmse_ch4['bias_ch4'].values[0]:.2f}, "
+ f"SD: {np.sqrt(rmse_ch4['var_ch4'].values[0]):.2f}",
fontsize="small",
)
axs[1, i].legend(fontsize="x-small", handlelength=0.4, frameon=False)
In [17]:
Copied!
plotting.plot_collocated_rmse(d_colloc_co2, d_colloc_ch4, "rmse")
plotting.plot_collocated_rmse(d_colloc_co2, d_colloc_ch4, "rmse")
Out[17]:
array([<Axes: title={'center': 'Carbon Dioxide (avg. RMSE:3.47)'}, xlabel='RMSE', ylabel='CO2 in ppm'>,
<Axes: title={'center': 'Methane (avg. RMSE:77.63)'}, xlabel='RMSE', ylabel='CH4 in ppb'>],
dtype=object)