Skip to content

Commit 356dc83

Browse files
committed
Add plot scripts for map and CDF for single field
1 parent f26dd86 commit 356dc83

File tree

2 files changed

+225
-0
lines changed

2 files changed

+225
-0
lines changed

detclim/plot_ensemble_cdf.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
from pathlib import Path
2+
3+
import matplotlib.pyplot as plt
4+
import numpy as np
5+
import pandas as pd
6+
import seaborn as sns
7+
import xarray as xr
8+
9+
import detclim.results_plot as rplt
10+
11+
12+
def main(dvar):
13+
scratch_dir = Path("/lustre/storm/nwp501/proj-shared/mkelleher/e3sm_scratch")
14+
ctl = "ctl"
15+
test = "clubb_c1-5p0pct"
16+
17+
cases = {
18+
ctl: "2025-09-16.F2010.ne30pg2_r05_oECv3_control",
19+
test: "2025-09-16.F2010.ne30pg2_r05_oECv3_clubb_c1_2p520000",
20+
}
21+
22+
ens_dirs = {_ens: Path(scratch_dir, _name, "run") for _ens, _name in cases.items()}
23+
24+
file_pattern = "{case}.eam.h0.aavg.nc"
25+
ens_file = {
26+
_ens: Path(ens_dirs[_ens], file_pattern.format(case=_name))
27+
for _ens, _name in cases.items()
28+
}
29+
data = {_ens: xr.open_dataset(_file) for _ens, _file in ens_file.items()}
30+
31+
_figwidth = 10 / 2.54
32+
_figheight = _figwidth * 0.9
33+
34+
data_ref = data[ctl][dvar].mean(dim="time")
35+
data_test = data[test][dvar].mean(dim="time")
36+
37+
n_q = data_ref.shape[0] // 2
38+
39+
all_ = np.concatenate((data_test.values, data_ref.values))
40+
min_all = np.min(all_)
41+
max_all = np.max(all_)
42+
43+
norm_ref = (data_ref - min_all) / (max_all - min_all)
44+
norm_test = (data_test - min_all) / (max_all - min_all)
45+
46+
bins = np.linspace(0, 1, n_q)
47+
48+
freq_ref, _ = np.histogram(norm_ref, bins=bins)
49+
freq_test, _ = np.histogram(norm_test, bins=bins)
50+
51+
cdf_ref = freq_ref.cumsum()
52+
cdf_test = freq_test.cumsum()
53+
54+
_xlabel = "Normalized annual global means"
55+
_ylabel = "N Ensemble members"
56+
57+
df_all = pd.concat(
58+
[
59+
pd.DataFrame(
60+
{
61+
_xlabel: bins,
62+
_ylabel: [0, *cdf_ref],
63+
"Simulation": rplt.fmt_case(ctl),
64+
}
65+
),
66+
pd.DataFrame(
67+
{
68+
_xlabel: bins,
69+
_ylabel: [0, *cdf_test],
70+
"Simulation": rplt.fmt_case(test),
71+
}
72+
),
73+
]
74+
)
75+
76+
fig, axes = plt.subplots(
77+
1,
78+
1,
79+
figsize=(_figwidth, _figheight),
80+
dpi=300,
81+
)
82+
sns.set_theme(
83+
context="paper",
84+
style="whitegrid",
85+
font="sans-serif",
86+
rc={"lines.linewidth": 1.5, "font.size": 8},
87+
)
88+
sns.lineplot(x=_xlabel, y=_ylabel, hue="Simulation", data=df_all, ax=axes)
89+
plt.tight_layout()
90+
fig.savefig(f"plt_cdf_{dvar}.pdf")
91+
fig.savefig(f"plt_cdf_{dvar}.png")
92+
93+
94+
if __name__ == "__main__":
95+
main(dvar="CLDLIQ")

detclim/plot_ensemble_mean_map.py

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
from pathlib import Path
2+
3+
import matplotlib.pyplot as plt
4+
import numpy as np
5+
import xarray as xr
6+
from cartopy import crs as ccrs
7+
8+
import detclim.results_plot as rplt
9+
10+
11+
def main():
12+
scratch_dir = Path("/lustre/storm/nwp501/proj-shared/mkelleher/e3sm_scratch")
13+
ctl = "ctl"
14+
test = "clubb_c1-5p0pct"
15+
params_hum = {
16+
"effgw_oro": "GW Orog",
17+
"clubb_c1": "CLUBB C1",
18+
"zmconv_c0_ocn": "ZM Conv C0-Ocean",
19+
"ctl": "Control",
20+
}
21+
22+
cases = {
23+
ctl: "2025-09-16.F2010.ne30pg2_r05_oECv3_control",
24+
test: "2025-09-16.F2010.ne30pg2_r05_oECv3_clubb_c1_2p520000",
25+
}
26+
27+
ens_dirs = {_ens: Path(scratch_dir, _name, "run") for _ens, _name in cases.items()}
28+
29+
file_pattern = "{case}.eam.h0.aavg.nc"
30+
ens_file = {
31+
_ens: Path(ens_dirs[_ens], file_pattern.format(case=_name))
32+
for _ens, _name in cases.items()
33+
}
34+
35+
files_2d = {
36+
_ens: Path(
37+
ens_file[_ens].parent,
38+
f"{cases[_ens]}.eam.h0.0001-03_0002-02_climo_ANN_r05_ensavg.nc",
39+
)
40+
for _ens in cases
41+
}
42+
43+
data_2d = {_ens: xr.open_dataset(_file) for _ens, _file in files_2d.items()}
44+
45+
proj = ccrs.Robinson()
46+
src_crs = ccrs.PlateCarree()
47+
48+
dvar = "CLDLIQ"
49+
title_props = {"fontsize": 8}
50+
_figwidth = 12.5 / 2.54
51+
plot_3panel = False
52+
53+
cbar_props = {"location": "right", "pad": 0.01, "shrink": 0.8}
54+
_figheight = _figwidth * 1.1
55+
fig = plt.figure(
56+
figsize=(_figwidth, _figheight),
57+
dpi=300,
58+
)
59+
axes = [
60+
fig.add_subplot(
61+
2,
62+
1,
63+
idx + 1,
64+
projection=proj,
65+
)
66+
for idx in range(2)
67+
]
68+
69+
diff_data = {}
70+
for _ens, _data in data_2d.items():
71+
_pltdata = _data.isel(time=0)
72+
if "lev" in _pltdata.coords:
73+
_pltdata = _pltdata.isel(lev=-1)
74+
else:
75+
_pltdata = _pltdata.squeeze()
76+
_pltdata = _pltdata.eval(dvar)
77+
if dvar in _data:
78+
_name = _data[dvar].long_name
79+
_units = _data[dvar].units
80+
diff_data[_ens] = _pltdata
81+
82+
_cf = axes[0].pcolormesh(
83+
_data["lon"],
84+
_data["lat"],
85+
diff_data[ctl],
86+
transform=src_crs,
87+
cmap="plasma",
88+
rasterized=True,
89+
)
90+
axes[0].set_title(f"{rplt.fmt_case(ctl)} mean", fontsize=title_props["fontsize"])
91+
_cax = fig.colorbar(_cf, ax=axes[0], **cbar_props)
92+
93+
_cax.set_label(_units, fontsize=title_props["fontsize"])
94+
95+
diff_2d = diff_data[test] - diff_data[ctl]
96+
_absmax = np.max(np.abs(diff_2d.quantile([0.01, 0.99])))
97+
_cf = axes[1].pcolormesh(
98+
data_2d[test]["lon"],
99+
data_2d[test]["lat"],
100+
diff_2d,
101+
vmin=-_absmax,
102+
vmax=_absmax,
103+
cmap="BrBG",
104+
transform=src_crs,
105+
rasterized=True,
106+
)
107+
axes[1].set_title(
108+
f"Difference {rplt.fmt_case(test)} - {rplt.fmt_case(ctl)}",
109+
fontsize=title_props["fontsize"],
110+
)
111+
_cax = fig.colorbar(_cf, ax=axes[1], **cbar_props)
112+
_cax.set_label(_units, fontsize=title_props["fontsize"])
113+
for axis in axes:
114+
axis.coastlines(linewidth=0.5)
115+
axis.gridlines(linestyle="--", linewidth=0.5, color="k")
116+
117+
fig.suptitle(f"{_name} [{_units}]", fontsize=12)
118+
plt.tight_layout()
119+
plt.savefig(
120+
f"test_diff_{_name.replace(' ', '_').replace('(', '').replace(')', '')}_"
121+
f"{ctl}-{test}.png"
122+
)
123+
plt.savefig(
124+
f"test_diff_{_name.replace(' ', '_').replace('(', '').replace(')', '')}_"
125+
f"{ctl}-{test}.pdf"
126+
)
127+
128+
129+
if __name__ == "__main__":
130+
main()

0 commit comments

Comments
 (0)