Skip to content

Commit d5c0045

Browse files
committed
Misc cleanup and rename global vars
1 parent 6862db6 commit d5c0045

File tree

1 file changed

+73
-200
lines changed

1 file changed

+73
-200
lines changed

proplot/rctools.py

Lines changed: 73 additions & 200 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from IPython import get_ipython
2020
except ModuleNotFoundError:
2121
def get_ipython():
22-
return None
22+
return
2323
from .utils import _warn_proplot, _counter, _benchmark, units
2424

2525
# Disable mathtext "missing glyph" warnings
@@ -33,7 +33,11 @@ def get_ipython():
3333
'ipython_autoreload', 'ipython_matplotlib',
3434
]
3535

36-
# Initialize
36+
# Dictionaries used to track custom proplot settings
37+
rcParamsShort = {}
38+
rcParamsLong = {}
39+
40+
# Dictionaries containing default settings
3741
defaultParamsShort = {
3842
'abc': False,
3943
'align': False,
@@ -242,38 +246,7 @@ def get_ipython():
242246
'text.usetex': False,
243247
'xtick.minor.visible': True,
244248
'ytick.minor.visible': True,
245-
246249
}
247-
rcParamsShort = {}
248-
rcParamsLong = {}
249-
250-
# Initialize user file
251-
_rc_file = os.path.join(os.path.expanduser('~'), '.proplotrc')
252-
if not os.path.isfile(_rc_file):
253-
def _tabulate(rcdict):
254-
string = ''
255-
maxlen = max(map(len, rcdict))
256-
for key, value in rcdict.items():
257-
value = '' if value is None else repr(value)
258-
space = ' ' * (maxlen - len(key) + 1) * int(bool(value))
259-
string += f'# {key}:{space}{value}\n'
260-
return string.strip()
261-
with open(_rc_file, 'x') as f:
262-
f.write(f"""
263-
#------------------------------------------------------
264-
# Use this file to customize settings
265-
# For descriptions of each key name see:
266-
# https://proplot.readthedocs.io/en/latest/rctools.html
267-
#------------------------------------------------------
268-
# ProPlot short name settings
269-
{_tabulate(defaultParamsShort)}
270-
#
271-
# ProPlot long name settings
272-
{_tabulate(defaultParamsLong)}
273-
#
274-
# Matplotlib settings
275-
{_tabulate(defaultParams)}
276-
""".strip())
277250

278251
# "Global" settings and the lower-level settings they change
279252
_rc_children = {
@@ -338,159 +311,42 @@ def _tabulate(rcdict):
338311
'xtick.major.pad', 'xtick.minor.pad',
339312
'ytick.major.pad', 'ytick.minor.pad'
340313
),
314+
'grid.color': (
315+
'gridminor.color',
316+
),
317+
'grid.linewidth': (
318+
'gridminor.linewidth',
319+
),
320+
'grid.linestyle': (
321+
'gridminor.linestyle',
322+
),
323+
'grid.alpha': (
324+
'gridminor.alpha',
325+
),
341326
}
342327

343-
# Names of the new settings
344-
RC_PARAMNAMES = {*rcParams.keys()}
345-
RC_SHORTNAMES = {
346-
'abc',
347-
'align',
348-
'alpha',
349-
'autoreload',
350-
'autosave',
351-
'borders',
352-
'cmap',
353-
'coast',
354-
'color',
355-
'cycle',
356-
'facecolor',
357-
'fontname',
358-
'geogrid',
359-
'grid',
360-
'gridminor',
361-
'gridratio',
362-
'inlinefmt',
363-
'innerborders',
364-
'lakes',
365-
'land',
366-
'large',
367-
'linewidth',
368-
'lut',
369-
'margin',
370-
'matplotlib',
371-
'ocean',
372-
'reso',
373-
'rgbcycle',
374-
'rivers',
375-
'share',
376-
'small',
377-
'span',
378-
'tickdir',
379-
'ticklen',
380-
'ticklenratio',
381-
'tickpad',
382-
'tickratio',
383-
'tight',
384-
}
385-
RC_LONGNAMES = {
386-
'abc.border',
387-
'abc.color',
388-
'abc.linewidth',
389-
'abc.loc',
390-
'abc.size',
391-
'abc.style',
392-
'abc.weight',
393-
'axes.alpha',
394-
'axes.formatter.timerotation',
395-
'axes.formatter.zerotrim',
396-
'axes.geogrid',
397-
'axes.gridminor',
398-
'borders.color',
399-
'borders.linewidth',
400-
'bottomlabel.color',
401-
'bottomlabel.size',
402-
'bottomlabel.weight',
403-
'coast.color',
404-
'coast.linewidth',
405-
'colorbar.axespad',
406-
'colorbar.extend',
407-
'colorbar.framealpha',
408-
'colorbar.frameon',
409-
'colorbar.grid',
410-
'colorbar.insetextend',
411-
'colorbar.insetlength',
412-
'colorbar.insetwidth',
413-
'colorbar.length',
414-
'colorbar.loc',
415-
'colorbar.width',
416-
'geoaxes.edgecolor',
417-
'geoaxes.facecolor',
418-
'geoaxes.linewidth',
419-
'geogrid.alpha',
420-
'geogrid.color',
421-
'geogrid.labels',
422-
'geogrid.labelsize',
423-
'geogrid.latmax',
424-
'geogrid.latstep',
425-
'geogrid.linestyle',
426-
'geogrid.linewidth',
427-
'geogrid.lonstep',
428-
'gridminor.alpha',
429-
'gridminor.color',
430-
'gridminor.linestyle',
431-
'gridminor.linewidth',
432-
'image.edgefix',
433-
'image.levels',
434-
'innerborders.color',
435-
'innerborders.linewidth',
436-
'lakes.color',
437-
'land.color',
438-
'leftlabel.color',
439-
'leftlabel.size',
440-
'leftlabel.weight',
441-
'ocean.color',
442-
'rightlabel.color',
443-
'rightlabel.size',
444-
'rightlabel.weight',
445-
'rivers.color',
446-
'rivers.linewidth',
447-
'subplots.axpad',
448-
'subplots.axwidth',
449-
'subplots.pad',
450-
'subplots.panelpad',
451-
'subplots.panelwidth',
452-
'suptitle.color',
453-
'suptitle.size',
454-
'suptitle.weight',
455-
'tick.labelcolor',
456-
'tick.labelsize',
457-
'tick.labelweight',
458-
'title.border',
459-
'title.color',
460-
'title.linewidth',
461-
'title.loc',
462-
'title.pad',
463-
'title.size',
464-
'title.weight',
465-
'toplabel.color',
466-
'toplabel.size',
467-
'toplabel.weight',
468-
}
469-
# Used by Axes.format, allows user to pass rc settings as keyword args,
470-
# way less verbose. For example, landcolor='b' vs. rc_kw={'land.color':'b'}.
471-
RC_NODOTSNAMES = { # useful for passing these as kwargs
472-
name.replace('.', ''): name for names in
473-
(RC_LONGNAMES, RC_PARAMNAMES, RC_SHORTNAMES)
474-
for name in names
328+
# Mapping of settings without "dots" to their full names. This lets us pass
329+
# all settings as kwargs, e.g. ax.format(landcolor='b') instead of the much
330+
# more verbose ax.format(rc_kw={'land.color':'b'}).
331+
_rc_nodots = {
332+
name.replace('.', ''): name
333+
for names in (defaultParamsLong, rcParams)
334+
for name in names.keys()
475335
}
476-
# Categories for returning dict of subcategory properties
477-
RC_CATEGORIES = {
478-
*(re.sub(r'\.[^.]*$', '', name) for names in
479-
(RC_LONGNAMES, RC_PARAMNAMES) for name in names),
480-
*(re.sub(r'\..*$', '', name) for names in
481-
(RC_LONGNAMES, RC_PARAMNAMES) for name in names)
482-
}
483-
484336

485-
def _to_points(key, value):
486-
"""Convert certain rc keys to the units "points"."""
487-
# See: https://matplotlib.org/users/customizing.html, all props matching
488-
# the below strings use the units 'points', except custom categories!
489-
if (isinstance(value, str)
490-
and key.split('.')[0] not in ('colorbar', 'subplots')
491-
and re.match('^.*(width|space|size|pad|len|small|large)$', key)):
492-
value = units(value, 'pt')
493-
return value
337+
# Category names, used for returning dicts of subcategory properties
338+
_rc_categories = {
339+
*(
340+
re.sub(r'\.[^.]*$', '', name)
341+
for names in (defaultParamsLong, rcParams)
342+
for name in names.keys()
343+
),
344+
*(
345+
re.sub(r'\..*$', '', name)
346+
for names in (defaultParamsLong, rcParams)
347+
for name in names.keys()
348+
)
349+
}
494350

495351

496352
def _get_config_paths():
@@ -521,10 +377,9 @@ def _get_synced_params(key, value):
521377
kw = {} # builtin properties that global setting applies to
522378
kw_long = {} # custom properties that global setting applies to
523379
kw_short = {} # short name properties
524-
if '.' not in key and key not in rcParamsShort:
525-
key = RC_NODOTSNAMES.get(key, key)
526380

527381
# Skip full name keys
382+
key = _sanitize_key(key)
528383
if '.' in key:
529384
pass
530385

@@ -538,10 +393,9 @@ def _get_synced_params(key, value):
538393
colors = mcm.cmap_d[cycle].colors
539394
except (KeyError, AttributeError):
540395
cycles = sorted(
541-
name for name,
542-
cmap in mcm.cmap_d.items() if isinstance(
543-
cmap,
544-
mcolors.ListedColormap))
396+
name for name, cmap in mcm.cmap_d.items()
397+
if isinstance(cmap, mcolors.ListedColormap)
398+
)
545399
raise ValueError(
546400
f'Invalid cycle name {cycle!r}. Options are: '
547401
', '.join(map(repr, cycles)) + '.'
@@ -550,9 +404,14 @@ def _get_synced_params(key, value):
550404
regcolors = colors + [(0.1, 0.1, 0.1)]
551405
elif mcolors.to_rgb('r') != (1.0, 0.0, 0.0): # reset
552406
regcolors = [
553-
(0.0, 0.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0),
554-
(0.75, 0.75, 0.0), (0.75, 0.75, 0.0), (0.0, 0.75, 0.75),
555-
(0.0, 0.0, 0.0)]
407+
(0.0, 0.0, 1.0),
408+
(1.0, 0.0, 0.0),
409+
(0.0, 1.0, 0.0),
410+
(0.75, 0.75, 0.0),
411+
(0.75, 0.75, 0.0),
412+
(0.0, 0.75, 0.75),
413+
(0.0, 0.0, 0.0)
414+
]
556415
else:
557416
regcolors = [] # no reset necessary
558417
for code, color in zip('brgmyck', regcolors):
@@ -648,7 +507,7 @@ def _get_synced_params(key, value):
648507
kw[key] = value
649508
else:
650509
raise KeyError(f'Invalid key {key!r}.')
651-
for name in RC_CHILDREN.get(key, ()):
510+
for name in _rc_children.get(key, ()):
652511
if name in rcParamsLong:
653512
kw_long[name] = value
654513
else:
@@ -657,14 +516,28 @@ def _get_synced_params(key, value):
657516

658517

659518
def _sanitize_key(key):
660-
"""Convert the key to a palatable value."""
519+
"""Ensure string and convert keys with omitted dots."""
661520
if not isinstance(key, str):
662521
raise KeyError(f'Invalid key {key!r}. Must be string.')
663-
if '.' not in key and key not in rcParamsShort:
664-
key = RC_NODOTSNAMES.get(key, key)
522+
if '.' not in key and key not in rcParamsShort: # speedup
523+
key = _rc_nodots.get(key, key)
665524
return key.lower()
666525

667526

527+
def _to_points(key, value):
528+
"""Convert certain rc keys to the units "points"."""
529+
# TODO: Incorporate into more sophisticated validation system
530+
# See: https://matplotlib.org/users/customizing.html, all props matching
531+
# the below strings use the units 'points', except custom categories!
532+
if (
533+
isinstance(value, str)
534+
and key.split('.')[0] not in ('colorbar', 'subplots')
535+
and re.match('^.*(width|space|size|pad|len|small|large)$', key)
536+
):
537+
value = units(value, 'pt')
538+
return value
539+
540+
668541
def _update_from_file(file):
669542
"""
670543
Apply updates from a file. This is largely copied from matplotlib.
@@ -927,7 +800,7 @@ def __getitem__(self, key):
927800
return kw[key]
928801
except KeyError:
929802
continue
930-
raise KeyError(f'Invalid property name {key!r}.')
803+
raise KeyError(f'Invalid setting name {key!r}.')
931804

932805
def __setattr__(self, attr, value):
933806
"""Pass the attribute and value to `~rc_configurator.__setitem__`."""
@@ -971,9 +844,9 @@ def _get_item(self, key, mode=None):
971844
except KeyError:
972845
continue
973846
if mode == 0:
974-
raise KeyError(f'Invalid property name {key!r}.')
847+
raise KeyError(f'Invalid setting name {key!r}.')
975848
else:
976-
return None
849+
return
977850

978851
def category(self, cat, *, trimcat=True, context=False):
979852
"""
@@ -992,10 +865,10 @@ def category(self, cat, *, trimcat=True, context=False):
992865
context mode dictionaries is omitted from the output dictionary.
993866
See `~rc_configurator.context`.
994867
"""
995-
if cat not in RC_CATEGORIES:
868+
if cat not in _rc_categories:
996869
raise ValueError(
997870
f'Invalid rc category {cat!r}. Valid categories are '
998-
', '.join(map(repr, RC_CATEGORIES)) + '.'
871+
', '.join(map(repr, _rc_categories)) + '.'
999872
)
1000873
kw = {}
1001874
mode = 0 if not context else None

0 commit comments

Comments
 (0)