Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
ncol = _notNone(ncol, 3)
pairs = [pairs[i * ncol:(i + 1) * ncol]
for i in range(len(pairs))] # to list of iterables
if list_of_lists: # remove empty lists, pops up in some examples
pairs = [ipairs for ipairs in pairs if ipairs]
# Now draw legend(s)
legs = []
width, height = self.get_size_inches()
# Individual legend
if not center:
# Optionally change order
# See: https://stackoverflow.com/q/10101141/4970632
# Example: If 5 columns, but final row length 3, columns 0-2 have
# N rows but 3-4 have N-1 rows.
ncol = _notNone(ncol, 3)
if order == 'C':
fpairs = []
# split into rows
split = [pairs[i * ncol:(i + 1) * ncol]
for i in range(len(pairs) // ncol + 1)]
# max possible row count, and columns in final row
nrowsmax, nfinalrow = len(split), len(split[-1])
nrows = [nrowsmax] * nfinalrow + \
[nrowsmax - 1] * (ncol - nfinalrow)
for col, nrow in enumerate(nrows): # iterate through cols
fpairs.extend(split[row][col] for row in range(nrow))
pairs = fpairs
# Make legend object
leg = mlegend.Legend(self, *zip(*pairs), ncol=ncol, loc=loc, **kwargs)
legs = [leg]
# Legend with centered rows, accomplished by drawing separate legends for
# i.e. was a 'values' or 'levels' attribute
elif not isinstance(locator, mticker.Locator):
# Get default maxn, try to allot 2em squares per label maybe?
# NOTE: Cannot use Axes.get_size_inches because this is a
# native matplotlib axes
width, height = self.figure.get_size_inches()
if orientation == 'horizontal':
scale = 3 # em squares alotted for labels
length = width * abs(self.get_position().width)
fontsize = kw_ticklabels.get('size', rc['xtick.labelsize'])
else:
scale = 1
length = height * abs(self.get_position().height)
fontsize = kw_ticklabels.get('size', rc['ytick.labelsize'])
maxn = _notNone(maxn, int(length / (scale * fontsize / 72)))
maxn_minor = _notNone(maxn_minor, int(
length / (0.5 * fontsize / 72)))
# Get locator
if tickminor and minorlocator is None:
step = 1 + len(locator) // max(1, maxn_minor)
minorlocator = locator[::step]
step = 1 + len(locator) // max(1, maxn)
locator = locator[::step]
# Final settings
locator = axistools.Locator(locator, **locator_kw)
formatter = axistools.Formatter(formatter, **formatter_kw)
width, height = self.figure.get_size_inches()
if orientation == 'horizontal':
scale = width * abs(self.get_position().width)
else:
scale = height * abs(self.get_position().height)
@docstring.add_snippets
def __call__(self, x, pos=None): # noqa: U100
"""
%(formatter.call)s
"""
# Limit digits to significant figures
if x == 0:
digits = 0
else:
digits = -int(np.log10(abs(x)) // 1)
decimal_point = AutoFormatter._get_default_decimal_point()
digits += self._sigfig - 1
x = np.round(x, digits)
string = ('{:.%df}' % max(0, digits)).format(x)
string = string.replace('.', decimal_point)
# Custom string formatting
"""
Return dictionaries of proplot and matplotlib settings loaded from the file.
"""
added = set()
path = os.path.expanduser(path)
kw_proplot = {}
kw_matplotlib = {}
with open(path, 'r') as fh:
for cnt, line in enumerate(fh):
# Parse line and ignore comments
stripped = line.split('#', 1)[0].strip()
if not stripped:
continue
pair = stripped.split(':', 1)
if len(pair) != 2:
warnings._warn_proplot(
f'Illegal line #{cnt + 1} in file {path!r}:\n{line!r}"'
)
continue
# Get key value pair
key, val = pair
key = key.strip()
val = val.strip()
if key in added:
warnings._warn_proplot(
f'Duplicate key {key!r} on line #{cnt + 1} in file {path!r}.'
)
added.add(key)
# *Very primitive* type conversion system for proplot settings.
# Matplotlib does this automatically.
'All files in this folder should have extension .txt.'
)
# Read data
loaded = {}
with open(path, 'r') as fh:
for cnt, line in enumerate(fh):
# Load colors from file
stripped = line.strip()
if not stripped or stripped[0] == '#':
continue
pair = tuple(
item.strip().lower() for item in line.split(':')
)
if len(pair) != 2 or not hex.match(pair[1]):
warnings._warn_proplot(
f'Illegal line #{cnt + 1} in file {path!r}:\n'
f'{line!r}\n'
f'Lines must be formatted as "name: hexcolor".'
)
continue
# Never overwrite "base" colors with xkcd colors.
# Only overwrite with user colors.
name, color = pair
if i == 0 and name in BASE_COLORS:
continue
loaded[name] = color
# Add every user color and every opencolor color and ensure XKCD
# colors are "perceptually distinct".
if i == 1:
mcolors.colorConverter.colors.update(loaded)
@docstring.add_snippets
def set_gamma(self, gamma=None, gamma1=None, gamma2=None):
"""
Modify the gamma value(s) and refresh the lookup table.
Parameters
----------
%(cmap.gamma)s
"""
gamma1 = _not_none(gamma1, gamma)
gamma2 = _not_none(gamma2, gamma)
if gamma1 is not None:
self._gamma1 = gamma1
if gamma2 is not None:
self._gamma2 = gamma2
self._init()
def __init__(self, version):
try:
major, minor, *_ = version.split('.')
major, minor = int(major), int(minor)
except (ValueError, AttributeError):
warnings._warn_proplot(
f"Invalid version {version!r}. Defaulting to '0.0'."
)
major = minor = 0
self._version = version
super().__init__([major, minor]) # then use builtin python list sorting
array += [[0, 4, 4, 5, 5, 0]]
labels += ('HSL saturation', 'HPL saturation')
if rgb:
array += [np.array([4, 4, 5, 5, 6, 6]) + 2 * int(saturation)]
labels += ('Red', 'Green', 'Blue')
fig, axs = ui.subplots(
array=array, span=False, share=1,
axwidth=axwidth, axpad='1em',
)
# Iterate through colormaps
mc = ms = mp = 0
cmaps = []
for cmap in args:
# Get colormap and avoid registering new names
name = cmap if isinstance(cmap, str) else getattr(cmap, 'name', None)
cmap = constructor.Colormap(cmap, N=N) # arbitrary cmap argument
if name is not None:
cmap.name = name
cmap._init()
cmaps.append(cmap)
# Get clipped RGB table
x = np.linspace(0, 1, N)
lut = cmap._lut[:-3, :3].copy()
rgb_data = lut.T # 3 by N
hcl_data = np.array([to_xyz(color, space='hcl') for color in lut]).T # 3 by N
hsl_data = [to_xyz(color, space='hsl')[1] for color in lut]
hpl_data = [to_xyz(color, space='hpl')[1] for color in lut]
# Plot channels
# If rgb is False, the zip will just truncate the other iterables
data = tuple(hcl_data)
# No mutable default args
xlabel_kw = xlabel_kw or {}
ylabel_kw = ylabel_kw or {}
xscale_kw = xscale_kw or {}
yscale_kw = yscale_kw or {}
xlocator_kw = xlocator_kw or {}
ylocator_kw = ylocator_kw or {}
xformatter_kw = xformatter_kw or {}
yformatter_kw = yformatter_kw or {}
xminorlocator_kw = xminorlocator_kw or {}
yminorlocator_kw = yminorlocator_kw or {}
# Flexible keyword args, declare defaults
xmargin = _not_none(xmargin, rc.get('axes.xmargin', context=True))
ymargin = _not_none(ymargin, rc.get('axes.ymargin', context=True))
xtickdir = _not_none(xtickdir, rc.get('xtick.direction', context=True))
ytickdir = _not_none(ytickdir, rc.get('ytick.direction', context=True))
xformatter = _not_none(xformatter=xformatter, xticklabels=xticklabels)
yformatter = _not_none(yformatter=yformatter, yticklabels=yticklabels)
xlocator = _not_none(xlocator=xlocator, xticks=xticks)
ylocator = _not_none(ylocator=ylocator, yticks=yticks)
xtickminor = _not_none(
xtickminor, rc.get('xtick.minor.visible', context=True)
)
ytickminor = _not_none(
ytickminor, rc.get('ytick.minor.visible', context=True)
)
xminorlocator = _not_none(
xminorlocator=xminorlocator, xminorticks=xminorticks,
)
yminorlocator = _not_none(
yminorlocator=yminorlocator, yminorticks=yminorticks,
label=None, labels=None, values=None,
**kwargs,
):
# Parse input args
name = func.__name__
autoformat = rc['autoformat']
legend_kw = legend_kw or {}
colorbar_kw = colorbar_kw or {}
labels = _not_none(
values=values,
labels=labels,
label=label,
legend_kw_labels=legend_kw.pop('labels', None),
)
if name in ('pie',): # add x coordinates as default pie chart labels
labels = _not_none(labels, x) # TODO: move to pie wrapper?
colorbar_legend_label = None # for colorbar or legend
# Handle legend labels. Several scenarios:
# 1. Always prefer input labels
# 2. Always add labels if this is a *named* dimension.
# 3. Even if not *named* dimension add labels if labels are string
# WARNING: Most methods that accept 2D arrays use columns of data, but when
# pandas DataFrame passed to hist, boxplot, or violinplot, rows of data
# assumed! This is fixed in parse_1d by converting to values.
sample = args[-1]
ncols = 1
if name in ('pie', 'boxplot', 'violinplot'):
# Functions handle multiple labels on their own
if labels is not None:
kwargs['labels'] = labels # error raised down the line
else: