Skip to content

Commit 67488bb

Browse files
committed
Add shift_hue and to_hex, return hex strings from color funcs
1 parent f102224 commit 67488bb

File tree

1 file changed

+165
-47
lines changed

1 file changed

+165
-47
lines changed

proplot/utils.py

Lines changed: 165 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,20 @@
1919
'edges',
2020
'edges2d',
2121
'units',
22-
'set_alpha',
2322
'set_hue',
24-
'set_luminance',
2523
'set_saturation',
26-
'scale_luminance',
24+
'set_luminance',
25+
'set_alpha',
26+
'shift_hue',
2727
'scale_saturation',
28+
'scale_luminance',
29+
'to_hex',
2830
'to_rgb',
2931
'to_xyz',
3032
'to_rgba',
3133
'to_xyza',
32-
# Deprecated
33-
'shade',
34-
'saturate',
34+
'shade', # deprecated
35+
'saturate', # deprecated
3536
]
3637

3738
NUMBER = re.compile(r'\A([-+]?[0-9._]+(?:[eE][-+]?[0-9_]+)?)(.*)\Z')
@@ -76,13 +77,9 @@
7677
"""
7778

7879
# Shared return values
79-
docstring.snippets['return.rgb'] = """
80-
color : 3-tuple
81-
An RGB tuple.
82-
"""
83-
docstring.snippets['return.rgba'] = """
84-
color : 4-tuple
85-
An RGBA tuple.
80+
docstring.snippets['return.hex'] = """
81+
color : str
82+
A HEX string.
8683
"""
8784

8885

@@ -92,6 +89,12 @@ def arange(min_, *args):
9289
example, ``plot.arange(2, 4)`` returns ``np.array([2, 3, 4])`` instead
9390
of ``np.array([2, 3])``. This command is useful for generating lists of
9491
tick locations or colorbar level boundaries.
92+
93+
See also
94+
--------
95+
proplot.axes.CartesianAxes.format
96+
proplot.constructor.Locator
97+
proplot.axes.apply_cmap
9598
"""
9699
# Optional arguments just like np.arange
97100
if len(args) == 0:
@@ -144,6 +147,8 @@ def edges(Z, axis=-1):
144147
See also
145148
--------
146149
edges2d
150+
proplot.axes.standardize_2d
151+
proplot.axes.apply_cmap
147152
"""
148153
Z = np.asarray(Z)
149154
Z = np.swapaxes(Z, axis, -1)
@@ -180,6 +185,7 @@ def edges2d(Z):
180185
See also
181186
--------
182187
edges
188+
proplot.axes.standardize_2d
183189
"""
184190
Z = np.asarray(Z)
185191
if Z.ndim != 2:
@@ -204,84 +210,111 @@ def edges2d(Z):
204210

205211
def _transform_color(func, color, space):
206212
"""
207-
Standardized input for color transformation functions.
213+
Standardize input for color transformation functions.
208214
"""
209215
*color, opacity = to_rgba(color)
210216
channels = list(to_xyz(color, space=space))
211217
channels = func(channels) # apply transform
212218
color = to_rgb(channels, space=space)
213219
color = tuple(np.clip(color, 0, 1)) # clip to valid range
214-
return (*color, opacity)
220+
return mcolors.to_hex((*color, opacity))
215221

216222

217223
@docstring.add_snippets
218-
def scale_saturation(color, scale=1, space='hcl'):
224+
def shift_hue(color, shift=0, space='hcl'):
219225
"""
220-
Scale the saturation channel of a color.
226+
Shift the hue channel of a color.
221227
222228
Parameters
223229
----------
224230
%(param.rgba)s
225-
scale : float, optoinal
226-
The HCL saturation channel is multiplied by this value.
231+
shift : float, optoinal
232+
The HCL hue channel is offset by this value.
227233
%(param.space)s
228234
229235
Returns
230236
-------
231-
%(return.rgba)s
237+
%(return.hex)s
232238
233239
See also
234240
--------
235-
set_saturation, scale_luminance
241+
set_hue
242+
set_saturation
243+
set_luminance
244+
set_alpha
245+
scale_saturation
246+
scale_luminance
236247
"""
237248
def func(channels):
238-
channels[1] *= scale
249+
channels[0] += shift
250+
channels[0] %= 360
239251
return channels
240252

241253
return _transform_color(func, color, space)
242254

243255

244256
@docstring.add_snippets
245-
def scale_luminance(color, scale=1, space='hcl'):
257+
def scale_saturation(color, scale=1, space='hcl'):
246258
"""
247-
Scale the luminance channel of a color.
259+
Scale the saturation channel of a color.
248260
249261
Parameters
250262
----------
251263
%(param.rgba)s
252264
scale : float, optoinal
253-
The luminance channel is multiplied by this value.
265+
The HCL saturation channel is multiplied by this value.
254266
%(param.space)s
255267
256268
Returns
257269
-------
258-
%(return.rgba)s
270+
%(return.hex)s
259271
260272
See also
261273
--------
262-
set_luminance, scale_saturation
274+
set_hue
275+
set_saturation
276+
set_luminance
277+
set_alpha
278+
shift_hue
279+
scale_luminance
263280
"""
264281
def func(channels):
265-
channels[2] *= scale
282+
channels[1] *= scale
266283
return channels
267284

268285
return _transform_color(func, color, space)
269286

270287

271288
@docstring.add_snippets
272-
def set_alpha(color, alpha):
289+
def scale_luminance(color, scale=1, space='hcl'):
273290
"""
274-
Return a color with the opacity channel set to the specified value.
291+
Scale the luminance channel of a color.
275292
276293
Parameters
277294
----------
278295
%(param.rgba)s
279-
alpha : float, optional
280-
The new opacity. Should be between ``0`` and ``1``.
296+
scale : float, optoinal
297+
The luminance channel is multiplied by this value.
298+
%(param.space)s
299+
300+
Returns
301+
-------
302+
%(return.hex)s
303+
304+
See also
305+
--------
306+
set_hue
307+
set_saturation
308+
set_luminance
309+
set_alpha
310+
shift_hue
311+
scale_saturation
281312
"""
282-
color = list(to_rgba(color))
283-
color[3] = alpha
284-
return tuple(color)
313+
def func(channels):
314+
channels[2] *= scale
315+
return channels
316+
317+
return _transform_color(func, color, space)
285318

286319

287320
@docstring.add_snippets
@@ -299,11 +332,16 @@ def set_hue(color, hue, space='hcl'):
299332
300333
Returns
301334
-------
302-
%(return.rgba)s
335+
%(return.hex)s
303336
304337
See also
305338
--------
306-
set_saturation, set_luminance
339+
set_saturation
340+
set_luminance
341+
set_alpha
342+
shift_hue
343+
scale_saturation
344+
scale_luminance
307345
"""
308346
def func(channels):
309347
channels[0] = hue
@@ -327,11 +365,16 @@ def set_saturation(color, saturation, space='hcl'):
327365
328366
Returns
329367
-------
330-
%(return.rgba)s
368+
%(return.hex)s
331369
332370
See also
333371
--------
334-
set_hue, set_luminance, scale_saturation
372+
set_hue
373+
set_luminance
374+
set_alpha
375+
shift_hue
376+
scale_saturation
377+
scale_luminance
335378
"""
336379
def func(channels):
337380
channels[1] = saturation
@@ -355,11 +398,16 @@ def set_luminance(color, luminance, space='hcl'):
355398
356399
Returns
357400
-------
358-
%(return.rgba)s
401+
%(return.hex)s
359402
360403
See also
361404
--------
362-
set_hue, set_saturation, scale_luminance
405+
set_hue
406+
set_saturation
407+
set_alpha
408+
shift_hue
409+
scale_saturation
410+
scale_luminance
363411
"""
364412
def func(channels):
365413
channels[2] = luminance
@@ -368,6 +416,62 @@ def func(channels):
368416
return _transform_color(func, color, space)
369417

370418

419+
@docstring.add_snippets
420+
def set_alpha(color, alpha):
421+
"""
422+
Return a color with the opacity channel set to the specified value.
423+
424+
Parameters
425+
----------
426+
%(param.rgba)s
427+
alpha : float, optional
428+
The new opacity. Should be between ``0`` and ``1``.
429+
430+
Returns
431+
-------
432+
%(return.hex)s
433+
434+
See also
435+
--------
436+
set_hue
437+
set_saturation
438+
set_luminance
439+
shift_hue
440+
scale_saturation
441+
scale_luminance
442+
"""
443+
color = list(to_rgba(color))
444+
color[3] = alpha
445+
return to_hex(color)
446+
447+
448+
def to_hex(color, space='rgb', cycle=None, keep_alpha=True):
449+
"""
450+
Translate the color in *any* format and from *any* colorspace
451+
to a HEX string. This is a generalization of `matplotlib.colors.to_hex`.
452+
453+
Parameters
454+
----------
455+
%(param.to_rgb)s
456+
keep_alpha : bool, optional
457+
Whether to keep the opacity channel. If ``True`` an 8-digit HEX
458+
is returned. Otherwise a 6-digit HEX is returned. Default is ``True``.
459+
460+
Returns
461+
-------
462+
%(return.hex)s
463+
464+
See also
465+
--------
466+
to_rgb
467+
to_rgba
468+
to_xyz
469+
to_xyza
470+
"""
471+
rgba = to_rgba(color, space=space, cycle=cycle)
472+
return mcolors.to_hex(rgba, keep_alpha=keep_alpha)
473+
474+
371475
@docstring.add_snippets
372476
def to_rgb(color, space='rgb', cycle=None):
373477
"""
@@ -381,11 +485,15 @@ def to_rgb(color, space='rgb', cycle=None):
381485
382486
Returns
383487
-------
384-
%(return.rgb)s
488+
color : 3-tuple
489+
An RGB tuple.
385490
386491
See also
387492
--------
388-
to_rgba, to_xyz
493+
to_hex
494+
to_rgba
495+
to_xyz
496+
to_xyza
389497
"""
390498
return to_rgba(color, space=space, cycle=cycle)[:3]
391499

@@ -403,11 +511,15 @@ def to_rgba(color, space='rgb', cycle=None):
403511
404512
Returns
405513
-------
406-
%(return.rgba)s
514+
color : 4-tuple
515+
An RGBA tuple.
407516
408517
See also
409518
--------
410-
to_rgb, to_xyza
519+
to_hex
520+
to_rgb
521+
to_xyz
522+
to_xyza
411523
"""
412524
# Convert color cycle strings
413525
if isinstance(color, str) and re.match(r'\AC[0-9]\Z', color):
@@ -490,7 +602,10 @@ def to_xyz(color, space='hcl'):
490602
491603
See also
492604
--------
493-
to_rgb, to_xyza
605+
to_hex
606+
to_rgb
607+
to_rgba
608+
to_xyza
494609
"""
495610
return to_xyza(color, space)[:3]
496611

@@ -514,7 +629,10 @@ def to_xyza(color, space='hcl'):
514629
515630
See also
516631
--------
517-
to_rgba, to_xyz
632+
to_hex
633+
to_rgb
634+
to_rgba
635+
to_xyz
518636
"""
519637
# Run tuple conversions
520638
# NOTE: Don't pass color tuple, because we may want to permit

0 commit comments

Comments
 (0)