Skip to content

Commit d283935

Browse files
committed
Cleanup internals and fix 2-level bug (fixes #407)
1 parent 0a0a241 commit d283935

File tree

1 file changed

+25
-19
lines changed

1 file changed

+25
-19
lines changed

proplot/colors.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@
339339
docstring._snippet_manager['colors.from_list'] = _from_list_docstring
340340

341341

342-
def _clip_colors(colors, clip=True, gray=0.2, warn=False):
342+
def _clip_colors(colors, clip=True, gray=0.2, warn_invalid=False):
343343
"""
344344
Clip impossible colors rendered in an HSL-to-RGB colorspace
345345
conversion. Used by `PerceptualColormap`.
@@ -349,13 +349,11 @@ def _clip_colors(colors, clip=True, gray=0.2, warn=False):
349349
colors : sequence of 3-tuple
350350
The RGB colors.
351351
clip : bool, optional
352-
If `clip` is ``True`` (the default), RGB channel values >1 are
353-
clipped to 1. Otherwise, the color is masked out as gray.
352+
If `clip` is ``True`` (the default), RGB channel values >1
353+
are clipped to 1. Otherwise, the color is masked out as gray.
354354
gray : float, optional
355-
The identical RGB channel values (gray color) to be used if
356-
`clip` is ``True``.
357-
warn : bool, optional
358-
Whether to issue warning when colors are clipped.
355+
The identical RGB channel values (gray color) to be used
356+
if `clip` is ``True``.
359357
"""
360358
colors = np.asarray(colors)
361359
under = colors < 0
@@ -364,15 +362,15 @@ def _clip_colors(colors, clip=True, gray=0.2, warn=False):
364362
colors[under], colors[over] = 0, 1
365363
else:
366364
colors[under | over] = gray
367-
if warn:
365+
if warn_invalid:
368366
msg = 'Clipped' if clip else 'Invalid'
369367
for i, name in enumerate('rgb'):
370368
if np.any(under[:, i]) or np.any(over[:, i]):
371369
warnings._warn_proplot(f'{msg} {name!r} channel.')
372370
return colors
373371

374372

375-
def _get_channel(color, channel, space='hcl'):
373+
def _color_channel(color, channel, space='hcl'):
376374
"""
377375
Get the hue, saturation, or luminance channel value from the input color. The
378376
color name `color` can optionally be a string with the format ``'color+x'``
@@ -586,7 +584,7 @@ def _load_colors(path, warn_on_failure=True):
586584
If ``True``, issue a warning when loading fails instead of raising an error.
587585
"""
588586
# Warn or raise error (matches Colormap._from_file behavior)
589-
if not os.path.exists(path):
587+
if not os.path.isfile(path):
590588
message = f'Failed to load color data file {path!r}. File not found.'
591589
if warn_on_failure:
592590
warnings._warn_proplot(message)
@@ -782,7 +780,7 @@ def _warn_or_raise(descrip, error=RuntimeError):
782780
warnings._warn_proplot(prefix + ' ' + descrip)
783781
else:
784782
raise error(prefix + ' ' + descrip)
785-
if not os.path.exists(path):
783+
if not os.path.isfile(path):
786784
return _warn_or_raise('File not found.', FileNotFoundError)
787785

788786
# Directly read segmentdata json file
@@ -1944,7 +1942,7 @@ def __init__(
19441942
for i, xyy in enumerate(array):
19451943
xyy = list(xyy) # make copy!
19461944
for j, y in enumerate(xyy[1:]): # modify the y values
1947-
xyy[j + 1] = _get_channel(y, key, space)
1945+
xyy[j + 1] = _color_channel(y, key, space)
19481946
data[key][i] = xyy
19491947
# Initialize
19501948
super().__init__(name, data, gamma=1.0, N=N, **kwargs)
@@ -2425,10 +2423,10 @@ def __init__(
24252423
# Instead user-reversed levels will always get passed here just as
24262424
# they are passed to SegmentedNorm inside plot.py
24272425
levels, descending = _sanitize_levels(levels)
2426+
vcenter = getattr(norm, 'vcenter', None)
24282427
vmin = norm.vmin = np.min(levels)
24292428
vmax = norm.vmax = np.max(levels)
24302429
bins, _ = _sanitize_levels(norm(levels))
2431-
vcenter = getattr(norm, 'vcenter', None)
24322430
mids = np.zeros((levels.size + 1,))
24332431
mids[1:-1] = 0.5 * (levels[1:] + levels[:-1])
24342432
mids[0], mids[-1] = mids[1], mids[-2]
@@ -2442,12 +2440,20 @@ def __init__(
24422440
# minimum 0 maximum 1, would mess up color distribution. However this is still
24432441
# not perfect... get asymmetric color intensity either side of central point.
24442442
# So we add special handling for diverging norms below to improve symmetry.
2445-
if unique in ('min', 'both'):
2446-
mids[0] += step * (mids[1] - mids[2])
2447-
if unique in ('max', 'both'):
2448-
mids[-1] += step * (mids[-2] - mids[-3])
2449-
mmin, mmax = np.min(mids), np.max(mids)
2450-
if vcenter is None:
2443+
if len(levels) == 2:
2444+
step = 0.5 # dummy step
2445+
mids[0] += step * (levels[0] - levels[1])
2446+
mids[-1] += step * (levels[-1] - levels[-2])
2447+
else:
2448+
if unique in ('min', 'both'):
2449+
offset = mids[1] - mids[2]
2450+
mids[0] += step * offset
2451+
if unique in ('max', 'both'):
2452+
offset = mids[-2] - mids[-3]
2453+
mids[-1] += step * offset
2454+
mmin = np.min(mids)
2455+
mmax = np.max(mids)
2456+
if vcenter is None: # not diverging norm or centered segmented norm
24512457
mids = _interpolate_scalar(mids, mmin, mmax, vmin, vmax)
24522458
else:
24532459
mask1, mask2 = mids < vcenter, mids >= vcenter

0 commit comments

Comments
 (0)