Skip to content

Commit db133b0

Browse files
henryhu123DennisTismenko
authored andcommitted
Resolve inconsistent NaN handling behaviour
Combine array masks rather than deleting masked points to maintain consistency across the project. Add appropriate test cases for validating color correctness for hlines and vlines. Fixes issue #13799.
1 parent 2883c90 commit db133b0

File tree

2 files changed

+88
-16
lines changed

2 files changed

+88
-16
lines changed

lib/matplotlib/axes/_axes.py

+20-16
Original file line numberDiff line numberDiff line change
@@ -1122,15 +1122,17 @@ def hlines(self, y, xmin, xmax, colors='k', linestyles='solid',
11221122
if not np.iterable(xmax):
11231123
xmax = [xmax]
11241124

1125-
y, xmin, xmax = cbook.delete_masked_points(y, xmin, xmax)
1126-
1125+
# Create and combine masked_arrays from input
1126+
y, xmin, xmax = cbook._combine_masks(y, xmin, xmax)
11271127
y = np.ravel(y)
1128-
xmin = np.resize(xmin, y.shape)
1129-
xmax = np.resize(xmax, y.shape)
1130-
1131-
verts = [((thisxmin, thisy), (thisxmax, thisy))
1132-
for thisxmin, thisxmax, thisy in zip(xmin, xmax, y)]
1133-
lines = mcoll.LineCollection(verts, colors=colors,
1128+
xmin = np.ma.resize(xmin, y.shape)
1129+
xmax = np.ma.resize(xmax, y.shape)
1130+
1131+
masked_verts = [np.ma.array([y_xmin, y_xmax])
1132+
for y_xmin, y_xmax in
1133+
zip(np.ma.array([xmin, y]).T,
1134+
np.ma.array([xmax, y]).T)]
1135+
lines = mcoll.LineCollection(masked_verts, colors=colors,
11341136
linestyles=linestyles, label=label)
11351137
self.add_collection(lines, autolim=False)
11361138
lines.update(kwargs)
@@ -1200,15 +1202,17 @@ def vlines(self, x, ymin, ymax, colors='k', linestyles='solid',
12001202
if not np.iterable(ymax):
12011203
ymax = [ymax]
12021204

1203-
x, ymin, ymax = cbook.delete_masked_points(x, ymin, ymax)
1204-
1205+
# Create and combine masked_arrays from input
1206+
x, ymin, ymax = cbook._combine_masks(x, ymin, ymax)
12051207
x = np.ravel(x)
1206-
ymin = np.resize(ymin, x.shape)
1207-
ymax = np.resize(ymax, x.shape)
1208-
1209-
verts = [((thisx, thisymin), (thisx, thisymax))
1210-
for thisx, thisymin, thisymax in zip(x, ymin, ymax)]
1211-
lines = mcoll.LineCollection(verts, colors=colors,
1208+
ymin = np.ma.resize(ymin, x.shape)
1209+
ymax = np.ma.resize(ymax, x.shape)
1210+
1211+
masked_verts = [np.ma.array([xymin, xymax])
1212+
for xymin, xymax in
1213+
zip(np.ma.array([x, ymin]).T,
1214+
np.ma.array([x, ymax]).T)]
1215+
lines = mcoll.LineCollection(masked_verts, colors=colors,
12121216
linestyles=linestyles, label=label)
12131217
self.add_collection(lines, autolim=False)
12141218
lines.update(kwargs)

lib/matplotlib/tests/test_axes.py

+68
Original file line numberDiff line numberDiff line change
@@ -3992,6 +3992,74 @@ def test_hlines():
39923992
ax5.set_ylim(0, 15)
39933993

39943994

3995+
def generate_hlines_with_colors_inputs():
3996+
colors = cycler('colors', [['red', 'green', 'blue', 'purple', 'orange']])
3997+
base_y = cycler(
3998+
'y', [[1, 2, 3, np.nan, 5], np.ma.masked_equal([1, 2, 3, 4, 5], 4)])
3999+
base_max = cycler('xmax', [np.ones(5)])
4000+
base_min = cycler('xmin', [0])
4001+
base_line_width = cycler('linewidth', [5])
4002+
original = base_y * base_min * base_max * colors * base_line_width
4003+
4004+
expect = {
4005+
'y': [1, 2, 3, 5],
4006+
'xmin': 0, 'xmax': [1, 2, 3, 5],
4007+
'colors': ['red', 'green', 'blue', 'orange']}
4008+
4009+
result = []
4010+
4011+
for i in original:
4012+
result.append({'original': i, 'expect': expect})
4013+
4014+
return result
4015+
4016+
4017+
@pytest.mark.parametrize('kwargs', generate_hlines_with_colors_inputs())
4018+
@check_figures_equal(extensions=["png"])
4019+
def test_hlines_with_colors(fig_test, fig_ref, kwargs):
4020+
fig_test, ax0 = plt.subplots()
4021+
test = kwargs.pop('original')
4022+
ax0.hlines(**test)
4023+
4024+
fig_ref, ax1 = plt.subplots()
4025+
ref = kwargs.pop('expect')
4026+
ax1.hlines(**ref)
4027+
4028+
4029+
def generate_vlines_with_colors_inputs():
4030+
colors = cycler('colors', [['red', 'green', 'blue', 'purple', 'orange']])
4031+
base_x = cycler(
4032+
'x', [[1, 2, 3, np.nan, 5], np.ma.masked_equal([1, 2, 3, 4, 5], 4)])
4033+
base_max = cycler('ymax', [np.ones(5)])
4034+
base_min = cycler('ymin', [0])
4035+
base_line_width = cycler('linewidth', [5])
4036+
original = base_x * base_min * base_max * colors * base_line_width
4037+
4038+
expect = {
4039+
'x': [1, 2, 3, 5],
4040+
'ymin': 0,
4041+
'ymax': [1, 2, 3, 5],
4042+
'colors': ['red', 'green', 'blue', 'orange']}
4043+
4044+
result = []
4045+
for i in original:
4046+
result.append({'original': i, 'expect': expect})
4047+
4048+
return result
4049+
4050+
4051+
@pytest.mark.parametrize('kwargs', generate_vlines_with_colors_inputs())
4052+
@check_figures_equal(extensions=["png"])
4053+
def test_vlines_with_colors(fig_test, fig_ref, kwargs):
4054+
fig_test, ax0 = plt.subplots()
4055+
test = kwargs.pop('original')
4056+
ax0.vlines(**test)
4057+
4058+
fig_ref, ax1 = plt.subplots()
4059+
ref = kwargs.pop('expect')
4060+
ax1.vlines(**ref)
4061+
4062+
39954063
@image_comparison(['step_linestyle', 'step_linestyle'], remove_text=True)
39964064
def test_step_linestyle():
39974065
x = y = np.arange(10)

0 commit comments

Comments
 (0)