diff --git a/CHANGELOG.md b/CHANGELOG.md index 37e61a25bc..55fd10f6b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Fixed issue with shapes and annotations plotting on the wrong y axis when supplied with a specific axis in the `yref` parameter [[#4177](https://github.com/plotly/plotly.py/pull/4177)] - Remove `use_2to3` setuptools arg, which is invalid in the latest Python and setuptools versions [[#4206](https://github.com/plotly/plotly.py/pull/4206)] - Fix [#4066](https://github.com/plotly/plotly.py/issues/4066) JupyterLab v4 giving tiny default graph height [[#4227](https://github.com/plotly/plotly.py/pull/4227)] + - Fixed issue with `colors.n_colors` where generated RGB color values were not being constrained to stay between 0 and 255 [[#4110](https://github.com/plotly/plotly.py/pull/4110)] ## [5.14.1] - 2023-04-05 diff --git a/packages/python/plotly/_plotly_utils/colors/__init__.py b/packages/python/plotly/_plotly_utils/colors/__init__.py index 06c0ff42a0..20c432094e 100644 --- a/packages/python/plotly/_plotly_utils/colors/__init__.py +++ b/packages/python/plotly/_plotly_utils/colors/__init__.py @@ -694,11 +694,19 @@ def n_colors(lowcolor, highcolor, n_colors, colortype="tuple"): incr_2 = diff_2 / (n_colors - 1) list_of_colors = [] + def _constrain_color(c): + if c > 255.0: + return 255.0 + elif c < 0.0: + return 0.0 + else: + return c + for index in range(n_colors): new_tuple = ( - lowcolor[0] + (index * incr_0), - lowcolor[1] + (index * incr_1), - lowcolor[2] + (index * incr_2), + _constrain_color(lowcolor[0] + (index * incr_0)), + _constrain_color(lowcolor[1] + (index * incr_1)), + _constrain_color(lowcolor[2] + (index * incr_2)), ) list_of_colors.append(new_tuple) diff --git a/packages/python/plotly/plotly/tests/test_core/test_colors/test_colors.py b/packages/python/plotly/plotly/tests/test_core/test_colors/test_colors.py index f8164499d5..2fb8e7831d 100644 --- a/packages/python/plotly/plotly/tests/test_core/test_colors/test_colors.py +++ b/packages/python/plotly/plotly/tests/test_core/test_colors/test_colors.py @@ -210,3 +210,30 @@ def test_sample_colorscale(self): colors.sample_colorscale("TuRbId_r", 12), colors.sequential.turbid_r, ) + + def test_n_colors(self): + # test that n_colors constrains values to between 0 and 255 + generated_colorscale = colors.n_colors( + lowcolor="rgb(255,0,0)", + highcolor="rgb(0,255,0)", + n_colors=14, + colortype="rgb", + ) + expected_colorscale = [ + "rgb(255.0, 0.0, 0.0)", + "rgb(235.3846153846154, 19.615384615384617, 0.0)", + "rgb(215.76923076923077, 39.23076923076923, 0.0)", + "rgb(196.15384615384613, 58.846153846153854, 0.0)", + "rgb(176.53846153846155, 78.46153846153847, 0.0)", + "rgb(156.9230769230769, 98.07692307692308, 0.0)", + "rgb(137.3076923076923, 117.69230769230771, 0.0)", + "rgb(117.69230769230768, 137.30769230769232, 0.0)", + "rgb(98.07692307692307, 156.92307692307693, 0.0)", + "rgb(78.46153846153845, 176.53846153846155, 0.0)", + "rgb(58.84615384615384, 196.15384615384616, 0.0)", + "rgb(39.230769230769226, 215.76923076923077, 0.0)", + "rgb(19.615384615384585, 235.38461538461542, 0.0)", + "rgb(0.0, 255.0, 0.0)", + ] + + self.assertEqual(generated_colorscale, expected_colorscale)