diff --git a/hydrodiy/plot/boxplot.py b/hydrodiy/plot/boxplot.py index 1fc716e3..9666a79b 100644 --- a/hydrodiy/plot/boxplot.py +++ b/hydrodiy/plot/boxplot.py @@ -594,7 +594,8 @@ def draw(self, ax=None, logscale=False, xoffset=0.): # Draw whiskers item = self.whiskers if item.show_line: - for cc in [[wqq1txt, bqq1txt], [wqq2txt, bqq2txt]]: + wnames = [[wqq1txt, bqq1txt], [wqq2txt, bqq2txt]] + for icc, cc in enumerate(wnames): # Get y data q1 = stats.loc[cc[0], colname] q2 = stats.loc[cc[1], colname] @@ -606,8 +607,8 @@ def draw(self, ax=None, logscale=False, xoffset=0.): ax.plot(x, y, lw=item.linewidth, color=item.linecolor, \ alpha=item.alpha) - element["bottom-whiskers"] = ax.get_lines()[-2] - element["top-whiskers"] = ax.get_lines()[-1] + element[f"bottom-whiskers{icc+1}"] = ax.get_lines()[-2] + element[f"top-whiskers{icc+1}"] = ax.get_lines()[-1] else: # Draw box bbox = FancyBboxPatch([i-ww/2+xoffset, q1], \ @@ -619,7 +620,7 @@ def draw(self, ax=None, logscale=False, xoffset=0.): alpha=item.alpha) ax.add_patch(bbox) - element["whiskers"] = ax.patches[-1] + element[f"whiskers{icc+1}"] = ax.patches[-1] # Cap width cw = capswidths[i] @@ -627,7 +628,7 @@ def draw(self, ax=None, logscale=False, xoffset=0.): # Draw caps item = self.caps if item.show_line and cw>0: - for qq in [wqq1txt, wqq2txt]: + for iqq, qq in enumerate([wqq1txt, wqq2txt]): q1 = stats.loc[qq, colname] x = [i-cw/5+xoffset, i+cw/5+xoffset] y = [q1]*2 @@ -635,8 +636,8 @@ def draw(self, ax=None, logscale=False, xoffset=0.): color=item.linecolor, \ alpha=item.alpha) - element["bottom-cap"] = ax.get_lines()[-2] - element["top-cap"] = ax.get_lines()[-1] + element[f"bottom-cap{iqq+1}"] = ax.get_lines()[-2] + element[f"top-cap{iqq+1}"] = ax.get_lines()[-1] # Box (quartile) values item = self.box @@ -793,3 +794,39 @@ def set_ylim(self, ylim, hide_offlimit_text=True): # Set axis limits self.ax.set_ylim(ylim) + + + def set_color(self, name_pattern, color, alpha=0.5): + """ Set color for selected boxes identied by + name_pattern. + + Parameters + ----------- + name_pattern : str + Pattern selection for box selection. + color : str + Color to set + alpha : float + Transparency level. + """ + props = ["color", "linecolor", \ + "edgecolor", "markeredgecolor", \ + "facecolor"] + + for ename, elems in self.elements.items(): + if not re.search(name_pattern, ename): + continue + + for on, obj in elems.items(): + for prop in props: + # Set color to element. + # Try all properties with try + try: + fun = getattr(obj, f"set_{prop}") + fun(color) + except: + pass + + if re.search("box", on): + obj.set_alpha(alpha) + diff --git a/hydrodiy/plot/tests/test_hyplot_boxplot.py b/hydrodiy/plot/tests/test_hyplot_boxplot.py index 8a13fcb4..8de638c7 100644 --- a/hydrodiy/plot/tests/test_hyplot_boxplot.py +++ b/hydrodiy/plot/tests/test_hyplot_boxplot.py @@ -136,6 +136,7 @@ def test_width_by_count(): def test_coverage(): + plt.close("all") fig, axs = plt.subplots(ncols=2) bx1 = Boxplot(data=DATA) @@ -150,6 +151,7 @@ def test_coverage(): def test_coverage_by(): + plt.close("all") fig, ax = plt.subplots() cat = DATA["cat"].copy() cat.loc[cat<3] = 0 @@ -160,6 +162,7 @@ def test_coverage_by(): def test_item_change(): + plt.close("all") fig, ax = plt.subplots() bx = Boxplot(data=DATA) bx.median.textformat = "%0.4f" @@ -169,6 +172,7 @@ def test_item_change(): def test_center(): + plt.close("all") fig, ax = plt.subplots() bx = Boxplot(data=DATA) bx.median.va = "bottom" @@ -197,6 +201,7 @@ def test_narrow(): df = pd.DataFrame(np.random.normal(size=(nval, nvar)), \ columns = ["data{0}".format(i) for i in range(nvar)]) + plt.close("all") fig, ax = plt.subplots() bx = Boxplot(style="narrow", data=df) bx.draw(ax=ax) @@ -209,6 +214,7 @@ def test_showtext(): df = pd.DataFrame(np.random.normal(size=(nval, nvar)), \ columns = ["data{0}".format(i) for i in range(nvar)]) + plt.close("all") fig, axs = plt.subplots(ncols=2) bx = Boxplot(data=df) bx.draw(ax=axs[0]) @@ -225,6 +231,7 @@ def test_center_text(): df = pd.DataFrame(np.random.normal(size=(nval, nvar)), \ columns = ["data{0}".format(i) for i in range(nvar)]) + plt.close("all") fig, axs = plt.subplots(ncols=2) bx = Boxplot(data=df) bx.draw(ax=axs[0]) @@ -241,6 +248,7 @@ def test_number_format(): df = pd.DataFrame(np.random.normal(size=(nval, nvar)), \ columns = ["data{0}".format(i) for i in range(nvar)]) + plt.close("all") fig, ax = plt.subplots() bx = Boxplot(data=df, number_format="3.3e") bx.draw(ax=ax) @@ -248,6 +256,7 @@ def test_number_format(): def test_change_elements(): + plt.close("all") fig, ax = plt.subplots() bx = Boxplot(data=DATA, show_text=True) bx.draw(ax=ax) @@ -257,7 +266,7 @@ def test_change_elements(): line.set_solid_capstyle("round") line.set_linewidth(8) - line = bx.elements["data1"]["top-cap"] + line = bx.elements["data1"]["top-cap1"] line.set_color("green") line.set_solid_capstyle("round") line.set_linewidth(6) @@ -270,6 +279,7 @@ def test_change_elements(): def test_set_ylim(): + plt.close("all") fig, axs = plt.subplots(ncols=2) ax = axs[0] bx = Boxplot(data=DATA) @@ -282,3 +292,22 @@ def test_set_ylim(): bx.set_ylim((1, y1), False) fig.savefig(FIMG /"bx20_set_ylim.png") + + +def test_set_color(): + plt.close("all") + fig, ax = plt.subplots() + bx = Boxplot(data=DATA) + bx.draw(ax=ax) + bx.set_color(".*a2$", "tab:red") + + fig.savefig(FIMG /"bx21_set_color.png") + + plt.close("all") + fig, ax = plt.subplots() + bx = Boxplot(data=DATA, style="narrow") + bx.draw(ax=ax) + bx.set_color(".*a2$", "tab:red") + + fig.savefig(FIMG /"bx22_set_color_narrow.png") +