Skip to content

Commit 6eafbbb

Browse files
authored
Merge branch 'main' into acordonez-patch-1
2 parents 5ba8466 + 959a527 commit 6eafbbb

File tree

10 files changed

+1038
-615
lines changed

10 files changed

+1038
-615
lines changed

doc/jupyter/Demo/Demo_1b_mean_climate.ipynb

Lines changed: 739 additions & 439 deletions
Large diffs are not rendered by default.

doc/obs_info_dictionary.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@
100100
},
101101
"GPCP-2-3": {
102102
"CMIP_CMOR_TABLE": "Amon",
103-
"MD5sum": "3792901034585d3d495722f10a0dfecb",
103+
"MD5sum": "036e14d0124f4d00921d58e3c1c3e9e1",
104104
"RefTrackingDate": "Wed Aug 4 12:22:10 2021",
105-
"filename": "pr_mon_GPCP-2-3_PCMDI_gn.200301-201812.AC.v20210804.nc",
105+
"filename": "pr_monC_GPCP-2-3_PCMDI_gn_197901-201907.AC.v20230516.nc",
106106
"period": "200301-201812",
107107
"shape": "(12, 72, 144)",
108-
"template": "pr/GPCP-2-3/v20210804/pr_mon_GPCP-2-3_PCMDI_gn.200301-201812.AC.v20210804.nc"
108+
"template": "NOAA-NCEI/GPCP-2-3/monC/pr/gn/v20230516/pr_monC_GPCP-2-3_PCMDI_gn_197901-201907.AC.v20230516.nc"
109109
},
110110
"TRMM-3B43v-7": {
111111
"CMIP_CMOR_TABLE": "Amon",

pcmdi_metrics/graphics/parallel_coordinate_plot/parallel_coordinate_plot_lib.py

Lines changed: 80 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ def parallel_coordinate_plot(
1515
metric_names,
1616
model_names,
1717
models_to_highlight=list(),
18+
models_to_highlight_by_line=True,
1819
models_to_highlight_colors=None,
1920
models_to_highlight_labels=None,
21+
models_to_highlight_markers=["s", "o", "^", "*"],
22+
models_to_highlight_markers_size=10,
2023
fig=None,
2124
ax=None,
2225
figsize=(15, 5),
@@ -30,14 +33,19 @@ def parallel_coordinate_plot(
3033
colormap="viridis",
3134
num_color=20,
3235
legend_off=False,
36+
legend_ncol=6,
37+
legend_bbox_to_anchor=(0.5, -0.14),
3338
logo_rect=None,
3439
logo_off=False,
3540
model_names2=None,
3641
group1_name="group1",
3742
group2_name="group2",
3843
comparing_models=None,
3944
fill_between_lines=False,
40-
fill_between_lines_colors=("green", "red"),
45+
fill_between_lines_colors=("red", "green"),
46+
arrow_between_lines=False,
47+
arrow_between_lines_colors=("red", "green"),
48+
arrow_alpha=1,
4149
vertical_center=None,
4250
vertical_center_line=False,
4351
vertical_center_line_label=None,
@@ -50,9 +58,12 @@ def parallel_coordinate_plot(
5058
- `data`: 2-d numpy array for metrics
5159
- `metric_names`: list, names of metrics for individual vertical axes (axis=1)
5260
- `model_names`: list, name of models for markers/lines (axis=0)
53-
- `models_to_highlight`: list, default=None, List of models to highlight as lines
61+
- `models_to_highlight`: list, default=None, List of models to highlight as lines or marker
62+
- `models_to_highlight_by_line`: bool, default=True, highlight as lines. If False, as marker
5463
- `models_to_highlight_colors`: list, default=None, List of colors for models to highlight as lines
5564
- `models_to_highlight_labels`: list, default=None, List of string labels for models to highlight as lines
65+
- `models_to_highlight_markers`: list, matplotlib markers for models to highlight if as marker
66+
- `models_to_highlight_markers_size`: float, size of matplotlib markers for models to highlight if as marker
5667
- `fig`: `matplotlib.figure` instance to which the parallel coordinate plot is plotted.
5768
If not provided, use current axes or create a new one. Optional.
5869
- `ax`: `matplotlib.axes.Axes` instance to which the parallel coordinate plot is plotted.
@@ -68,6 +79,8 @@ def parallel_coordinate_plot(
6879
- `colormap`: string, default='viridis', matplotlib colormap
6980
- `num_color`: integer, default=20, how many color to use.
7081
- `legend_off`: bool, default=False, turn off legend
82+
- `legend_ncol`: integer, default=6, number of columns for legend text
83+
- `legend_bbox_to_anchor`: tuple, defulat=(0.5, -0.14), set legend box location
7184
- `logo_rect`: sequence of float. The dimensions [left, bottom, width, height] of the new Axes.
7285
All quantities are in fractions of figure width and height. Optional.
7386
- `logo_off`: bool, default=False, turn off PMP logo
@@ -76,7 +89,10 @@ def parallel_coordinate_plot(
7689
- `group2_name`: string, needed for violin plot legend if splited to two groups, for the 2nd group. Default is 'group2'.
7790
- `comparing_models`: tuple or list containing two strings for models to compare with colors filled between the two lines.
7891
- `fill_between_lines`: bool, default=False, fill color between lines for models in comparing_models
79-
- `fill_between_lines_colors`: tuple or list containing two strings for colors filled between the two lines. Default=('green', 'red')
92+
- `fill_between_lines_colors`: tuple or list containing two strings of colors for filled between the two lines. Default=('red', 'green')
93+
- `arrow_between_lines`: bool, default=False, place arrows between two lines for models in comparing_models
94+
- `arrow_between_lines_colors`: tuple or list containing two strings of colors for arrow between the two lines. Default=('red', 'green')
95+
- `arrow_alpha`: float, default=1, transparency of arrow (faction between 0 to 1)
8096
- `vertical_center`: string ("median", "mean")/float/integer, default=None, adjust range of vertical axis to set center of vertical axis as median, mean, or given number
8197
- `vertical_center_line`: bool, default=False, show median as line
8298
- `vertical_center_line_label`: str, default=None, label in legend for the horizontal vertical center line. If not given, it will be automatically assigned. It can be turned off by "off"
@@ -231,7 +247,18 @@ def parallel_coordinate_plot(
231247
else:
232248
label = model
233249

234-
ax.plot(range(N), zs[j, :], "-", c=color, label=label, lw=3)
250+
if models_to_highlight_by_line:
251+
ax.plot(range(N), zs[j, :], "-", c=color, label=label, lw=3)
252+
else:
253+
ax.plot(
254+
range(N),
255+
zs[j, :],
256+
models_to_highlight_markers[mh_index],
257+
c=color,
258+
label=label,
259+
markersize=models_to_highlight_markers_size,
260+
)
261+
235262
mh_index += 1
236263
else:
237264
if identify_all_models:
@@ -251,8 +278,8 @@ def parallel_coordinate_plot(
251278
vertical_center_line_label = None
252279
ax.plot(range(N), zs_middle, "-", c="k", label=vertical_center_line_label, lw=1)
253280

254-
# Fill between lines
255-
if fill_between_lines and (comparing_models is not None):
281+
# Compare two models
282+
if comparing_models is not None:
256283
if isinstance(comparing_models, tuple) or (
257284
isinstance(comparing_models, list) and len(comparing_models) == 2
258285
):
@@ -261,24 +288,49 @@ def parallel_coordinate_plot(
261288
m2 = model_names.index(comparing_models[1])
262289
y1 = zs[m1, :]
263290
y2 = zs[m2, :]
264-
ax.fill_between(
265-
x,
266-
y1,
267-
y2,
268-
where=y2 >= y1,
269-
facecolor=fill_between_lines_colors[0],
270-
interpolate=True,
271-
alpha=0.5,
272-
)
273-
ax.fill_between(
274-
x,
275-
y1,
276-
y2,
277-
where=y2 <= y1,
278-
facecolor=fill_between_lines_colors[1],
279-
interpolate=True,
280-
alpha=0.5,
281-
)
291+
292+
# Fill between lines
293+
if fill_between_lines:
294+
ax.fill_between(
295+
x,
296+
y1,
297+
y2,
298+
where=(y2 > y1),
299+
facecolor=fill_between_lines_colors[0],
300+
interpolate=False,
301+
alpha=0.5,
302+
)
303+
ax.fill_between(
304+
x,
305+
y1,
306+
y2,
307+
where=(y2 < y1),
308+
facecolor=fill_between_lines_colors[1],
309+
interpolate=False,
310+
alpha=0.5,
311+
)
312+
313+
if arrow_between_lines:
314+
# Add vertical arrows
315+
for xi, yi1, yi2 in zip(x, y1, y2):
316+
if yi2 > yi1:
317+
arrow_color = arrow_between_lines_colors[0]
318+
elif yi2 < yi1:
319+
arrow_color = arrow_between_lines_colors[1]
320+
else:
321+
arrow_color = None
322+
arrow_length = yi2 - yi1
323+
ax.arrow(
324+
xi,
325+
yi1,
326+
0,
327+
arrow_length,
328+
color=arrow_color,
329+
length_includes_head=True,
330+
alpha=arrow_alpha,
331+
width=0.05,
332+
head_width=0.15,
333+
)
282334

283335
ax.set_xlim(-0.5, N - 0.5)
284336
ax.set_xticks(range(N))
@@ -288,7 +340,10 @@ def parallel_coordinate_plot(
288340
ax.set_title(title, fontsize=18)
289341

290342
if not legend_off:
291-
ax.legend(loc="upper center", ncol=6, bbox_to_anchor=(0.5, -0.14))
343+
# ax.legend(loc="upper center", ncol=6, bbox_to_anchor=(0.5, -0.14))
344+
ax.legend(
345+
loc="upper center", ncol=legend_ncol, bbox_to_anchor=legend_bbox_to_anchor
346+
)
292347

293348
if not logo_off:
294349
fig, ax = add_logo(fig, ax, logo_rect)

pcmdi_metrics/graphics/portrait_plot/portrait_plot_example.ipynb

Lines changed: 44 additions & 56 deletions
Large diffs are not rendered by default.

pcmdi_metrics/graphics/portrait_plot/portrait_plot_lib.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ def portrait_plot(
1616
ax=None,
1717
annotate=False,
1818
annotate_data=None,
19+
annotate_textcolors=("black", "white"),
20+
annotate_textcolors_threshold=(-2, 2),
1921
annotate_fontsize=15,
2022
annotate_format="{x:.2f}",
2123
figsize=(12, 10),
@@ -61,6 +63,8 @@ def portrait_plot(
6163
- `annotate`: bool, default=False, add annotating text if true,
6264
but work only for heatmap style map (i.e., no triangles)
6365
- `annotate_data`: 2d numpy array, default=None. If None, the image's data is used. Optional.
66+
- `annotate_textcolors`: Tuple. A pair of colors for annotation text. Default is ("black", "white")
67+
- `annotate_textcolors_threshold`: Tuple or float. Value in data units according to which the colors from textcolors are applied. Default=(-2, 2)
6468
- `annotate_fontsize`: number (int/float), default=15. Font size for annotation
6569
- `annotate_format`: format for annotate value, default="{x:.2f}"
6670
- `figsize`: tuple of two numbers (width, height), default=(12, 10), figure size in inches
@@ -169,13 +173,14 @@ def portrait_plot(
169173
sys.exit("Error: annotate_data has different size than data")
170174
else:
171175
annotate_data = data
172-
annotate_heatmap(
176+
ax = annotate_heatmap(
173177
im,
174178
ax=ax,
175179
data=data,
176180
annotate_data=annotate_data,
177181
valfmt=annotate_format,
178-
threshold=(2, -2),
182+
textcolors=annotate_textcolors,
183+
threshold=annotate_textcolors_threshold,
179184
fontsize=annotate_fontsize,
180185
)
181186

@@ -501,6 +506,8 @@ def annotate_heatmap(
501506
text = ax.text(j + 0.5, i + 0.5, valfmt(annotate_data[i, j], None), **kw)
502507
texts.append(text)
503508

509+
return ax
510+
504511

505512
# ======================================================================
506513
# Portrait plot 2 (two triangles)

pcmdi_metrics/graphics/share/read_json_mean_clim.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,15 @@ def extract_data(results_dict, var_list, region, stat, season, mip, debug=False)
148148
Return a pandas dataframe for metric numbers at given region/stat/season.
149149
Rows: models, Columns: variables (i.e., 2d array)
150150
"""
151-
model_list = sorted(list(results_dict[var_list[0]]["RESULTS"].keys()))
151+
model_list = sorted(
152+
list(results_dict[var_list[0]]["RESULTS"].keys()), key=str.casefold
153+
)
152154
# update model_list
153155
if "rlut" in list(results_dict.keys()):
154156
if "rlut" in list(results_dict["rlut"]["RESULTS"].keys()):
155-
model_list = sorted(list(results_dict["rlut"]["RESULTS"].keys()))
157+
model_list = sorted(
158+
list(results_dict["rlut"]["RESULTS"].keys()), key=str.casefold
159+
)
156160

157161
print("extract_data:: model_list: ", model_list)
158162

0 commit comments

Comments
 (0)