Skip to content

Commit 1476824

Browse files
authored
Merge branch 'main' into mean_clim_loca2_analysis
2 parents e6345a1 + 26326e5 commit 1476824

File tree

3 files changed

+125
-82
lines changed

3 files changed

+125
-82
lines changed

pcmdi_metrics/graphics/parallel_coordinate_plot/parallel_coordinate_plot_lib.py

Lines changed: 72 additions & 24 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),
@@ -37,7 +40,10 @@ def parallel_coordinate_plot(
3740
group2_name="group2",
3841
comparing_models=None,
3942
fill_between_lines=False,
40-
fill_between_lines_colors=("green", "red"),
43+
fill_between_lines_colors=("red", "green"),
44+
arrow_between_lines=False,
45+
arrow_between_lines_colors=("red", "green"),
46+
arrow_alpha=1,
4147
vertical_center=None,
4248
vertical_center_line=False,
4349
vertical_center_line_label=None,
@@ -50,9 +56,12 @@ def parallel_coordinate_plot(
5056
- `data`: 2-d numpy array for metrics
5157
- `metric_names`: list, names of metrics for individual vertical axes (axis=1)
5258
- `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
59+
- `models_to_highlight`: list, default=None, List of models to highlight as lines or marker
60+
- `models_to_highlight_by_line`: bool, default=True, highlight as lines. If False, as marker
5461
- `models_to_highlight_colors`: list, default=None, List of colors for models to highlight as lines
5562
- `models_to_highlight_labels`: list, default=None, List of string labels for models to highlight as lines
63+
- `models_to_highlight_markers`: list, matplotlib markers for models to highlight if as marker
64+
- `models_to_highlight_markers_size`: float, size of matplotlib markers for models to highlight if as marker
5665
- `fig`: `matplotlib.figure` instance to which the parallel coordinate plot is plotted.
5766
If not provided, use current axes or create a new one. Optional.
5867
- `ax`: `matplotlib.axes.Axes` instance to which the parallel coordinate plot is plotted.
@@ -76,7 +85,10 @@ def parallel_coordinate_plot(
7685
- `group2_name`: string, needed for violin plot legend if splited to two groups, for the 2nd group. Default is 'group2'.
7786
- `comparing_models`: tuple or list containing two strings for models to compare with colors filled between the two lines.
7887
- `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')
88+
- `fill_between_lines_colors`: tuple or list containing two strings of colors for filled between the two lines. Default=('red', 'green')
89+
- `arrow_between_lines`: bool, default=False, place arrows between two lines for models in comparing_models
90+
- `arrow_between_lines_colors`: tuple or list containing two strings of colors for arrow between the two lines. Default=('red', 'green')
91+
- `arrow_alpha`: float, default=1, transparency of arrow (faction between 0 to 1)
8092
- `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
8193
- `vertical_center_line`: bool, default=False, show median as line
8294
- `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 +243,18 @@ def parallel_coordinate_plot(
231243
else:
232244
label = model
233245

234-
ax.plot(range(N), zs[j, :], "-", c=color, label=label, lw=3)
246+
if models_to_highlight_by_line:
247+
ax.plot(range(N), zs[j, :], "-", c=color, label=label, lw=3)
248+
else:
249+
ax.plot(
250+
range(N),
251+
zs[j, :],
252+
models_to_highlight_markers[mh_index],
253+
c=color,
254+
label=label,
255+
markersize=models_to_highlight_markers_size,
256+
)
257+
235258
mh_index += 1
236259
else:
237260
if identify_all_models:
@@ -251,8 +274,8 @@ def parallel_coordinate_plot(
251274
vertical_center_line_label = None
252275
ax.plot(range(N), zs_middle, "-", c="k", label=vertical_center_line_label, lw=1)
253276

254-
# Fill between lines
255-
if fill_between_lines and (comparing_models is not None):
277+
# Compare two models
278+
if comparing_models is not None:
256279
if isinstance(comparing_models, tuple) or (
257280
isinstance(comparing_models, list) and len(comparing_models) == 2
258281
):
@@ -261,24 +284,49 @@ def parallel_coordinate_plot(
261284
m2 = model_names.index(comparing_models[1])
262285
y1 = zs[m1, :]
263286
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-
)
287+
288+
# Fill between lines
289+
if fill_between_lines:
290+
ax.fill_between(
291+
x,
292+
y1,
293+
y2,
294+
where=(y2 > y1),
295+
facecolor=fill_between_lines_colors[0],
296+
interpolate=False,
297+
alpha=0.5,
298+
)
299+
ax.fill_between(
300+
x,
301+
y1,
302+
y2,
303+
where=(y2 < y1),
304+
facecolor=fill_between_lines_colors[1],
305+
interpolate=False,
306+
alpha=0.5,
307+
)
308+
309+
if arrow_between_lines:
310+
# Add vertical arrows
311+
for xi, yi1, yi2 in zip(x, y1, y2):
312+
if yi2 > yi1:
313+
arrow_color = arrow_between_lines_colors[0]
314+
elif yi2 < yi1:
315+
arrow_color = arrow_between_lines_colors[1]
316+
else:
317+
arrow_color = None
318+
arrow_length = yi2 - yi1
319+
ax.arrow(
320+
xi,
321+
yi1,
322+
0,
323+
arrow_length,
324+
color=arrow_color,
325+
length_includes_head=True,
326+
alpha=arrow_alpha,
327+
width=0.05,
328+
head_width=0.15,
329+
)
282330

283331
ax.set_xlim(-0.5, N - 0.5)
284332
ax.set_xticks(range(N))

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)

0 commit comments

Comments
 (0)