Skip to content

Commit f37fd3c

Browse files
Merge pull request #2627 from plotly/issue-2618
KeyError when running the create_dendrogram example
2 parents d601477 + 969aba4 commit f37fd3c

File tree

1 file changed

+51
-9
lines changed

1 file changed

+51
-9
lines changed

Diff for: packages/python/plotly/plotly/figure_factory/_dendrogram.py

+51-9
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,21 @@ def create_dendrogram(
2525
color_threshold=None,
2626
):
2727
"""
28-
Function that returns a dendrogram Plotly figure object.
28+
Function that returns a dendrogram Plotly figure object. This is a thin
29+
wrapper around scipy.cluster.hierarchy.dendrogram.
2930
3031
See also https://dash.plot.ly/dash-bio/clustergram.
3132
3233
:param (ndarray) X: Matrix of observations as array of arrays
3334
:param (str) orientation: 'top', 'right', 'bottom', or 'left'
3435
:param (list) labels: List of axis category labels(observation labels)
35-
:param (list) colorscale: Optional colorscale for dendrogram tree
36+
:param (list) colorscale: Optional colorscale for the dendrogram tree.
37+
Requires 8 colors to be specified, the 7th of
38+
which is ignored. With scipy>=1.5.0, the 2nd, 3rd
39+
and 6th are used twice as often as the others.
40+
Given a shorter list, the missing values are
41+
replaced with defaults and with a longer list the
42+
extra values are ignored.
3643
:param (function) distfun: Function to compute the pairwise distance from
3744
the observations
3845
:param (function) linkagefun: Function to compute the linkage matrix from
@@ -160,8 +167,8 @@ def __init__(
160167
if len(self.zero_vals) > len(yvals) + 1:
161168
# If the length of zero_vals is larger than the length of yvals,
162169
# it means that there are wrong vals because of the identicial samples.
163-
# Three and more identicial samples will make the yvals of spliting center into 0 and it will \
164-
# accidentally take it as leaves.
170+
# Three and more identicial samples will make the yvals of spliting
171+
# center into 0 and it will accidentally take it as leaves.
165172
l_border = int(min(self.zero_vals))
166173
r_border = int(max(self.zero_vals))
167174
correct_leaves_pos = range(
@@ -185,6 +192,9 @@ def get_color_dict(self, colorscale):
185192

186193
# These are the color codes returned for dendrograms
187194
# We're replacing them with nicer colors
195+
# This list is the colors that can be used by dendrogram, which were
196+
# determined as the combination of the default above_threshold_color and
197+
# the default color palette (see scipy/cluster/hierarchy.py)
188198
d = {
189199
"r": "red",
190200
"g": "green",
@@ -193,26 +203,58 @@ def get_color_dict(self, colorscale):
193203
"m": "magenta",
194204
"y": "yellow",
195205
"k": "black",
206+
# TODO: 'w' doesn't seem to be in the default color
207+
# palette in scipy/cluster/hierarchy.py
196208
"w": "white",
197209
}
198210
default_colors = OrderedDict(sorted(d.items(), key=lambda t: t[0]))
199211

200212
if colorscale is None:
201-
colorscale = [
213+
rgb_colorscale = [
202214
"rgb(0,116,217)", # blue
203215
"rgb(35,205,205)", # cyan
204216
"rgb(61,153,112)", # green
205217
"rgb(40,35,35)", # black
206218
"rgb(133,20,75)", # magenta
207219
"rgb(255,65,54)", # red
208220
"rgb(255,255,255)", # white
209-
"rgb(255,220,0)",
210-
] # yellow
221+
"rgb(255,220,0)", # yellow
222+
]
223+
else:
224+
rgb_colorscale = colorscale
211225

212226
for i in range(len(default_colors.keys())):
213227
k = list(default_colors.keys())[i] # PY3 won't index keys
214-
if i < len(colorscale):
215-
default_colors[k] = colorscale[i]
228+
if i < len(rgb_colorscale):
229+
default_colors[k] = rgb_colorscale[i]
230+
231+
# add support for cyclic format colors as introduced in scipy===1.5.0
232+
# before this, the colors were named 'r', 'b', 'y' etc., now they are
233+
# named 'C0', 'C1', etc. To keep the colors consistent regardless of the
234+
# scipy version, we try as much as possible to map the new colors to the
235+
# old colors
236+
# this mapping was found by inpecting scipy/cluster/hierarchy.py (see
237+
# comment above).
238+
new_old_color_map = [
239+
("C0", "b"),
240+
("C1", "g"),
241+
("C2", "r"),
242+
("C3", "c"),
243+
("C4", "m"),
244+
("C5", "y"),
245+
("C6", "k"),
246+
("C7", "g"),
247+
("C8", "r"),
248+
("C9", "c"),
249+
]
250+
for nc, oc in new_old_color_map:
251+
try:
252+
default_colors[nc] = default_colors[oc]
253+
except KeyError:
254+
# it could happen that the old color isn't found (if a custom
255+
# colorscale was specified), in this case we set it to an
256+
# arbitrary default.
257+
default_colors[n] = "rgb(0,116,217)"
216258

217259
return default_colors
218260

0 commit comments

Comments
 (0)