mplcyberpunk
mplcyberpunk copied to clipboard
Option for changing colors
Could this feature please be added?
Custom colors for plot and custom gradient colors for graph area
Thankyou
What I mean to say Is that I want to have this sort of plot using your theme:
How can I possibly achieve this setting?
edit: another example:
as a workaround, can you try plotting the positive and negative parts separately with different colors?
I have been trying to get amount the function and tweak it to fulfil the requirement.
Since I need only the line color and gradient, I removed all other functions to make it more straightforward on my local machine.
Here is the code (core.py
) that works for me:
from itertools import groupby
import numpy as np
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
from matplotlib.patches import Polygon
def add_glow_effects(color_positive: str = '#0000ff',
color_negative: str = '#ff0000',
alpha_gradientglow: float = 1.0):
add_gradient_fill(alpha_gradientglow, color_positive, color_negative, )
change_line_color(color_positive, color_negative)
def change_line_color(color_positive: str = '#0000ff',
color_negative: str = '#ff0000'):
ax = plt.gca()
lines = ax.get_lines()
for line_element in lines:
if not isinstance(line_element, Line2D):
continue
x, y = line_element.get_data(orig=False)
x, y = optimize_lines(list(x), list(y))
lines_list = list_form(x, y)
for line in lines_list:
y_avg = sum(line[1]) / len(line[1])
if y_avg >= 0:
color = color_positive
else:
color = color_negative
line = Line2D(line[0], line[1], linewidth=line_element.get_linewidth(), color=color)
data = list(line.get_data(orig=False))
linewidth = line.get_linewidth()
ax.plot(data[0], data[1], linewidth=linewidth, color=color)
# noinspection PyArgumentList
def add_gradient_fill(alpha_gradientglow: float = 1.0,
color_positive: str = '#00ff00',
color_negative: str = '#ff0000'):
"""Add a gradient fill under each line,
i.e. faintly color the area below the line."""
ax = plt.gca()
lines = ax.get_lines()
for line_element in lines:
if not isinstance(line_element, Line2D):
continue
x, y = line_element.get_data(orig=False)
alpha = line_element.get_alpha()
alpha = 1.0 if alpha is None else alpha
x, y = optimize_lines(list(x), list(y))
lines_list = list_form(x, y)
# get max from every second list of every list in this list
y_values = []
for i in lines_list:
for j in i[1]:
y_values.append(j)
# y_max_global = max(y_values)
# y_min_global = min(y_values)
del y_values
for line in lines_list:
y_avg = sum(line[1]) / len(line[1])
# don't add gradient fill for glow effect lines:
if hasattr(line, 'is_glow_line') and line.is_glow_line:
continue
line = Line2D(line[0], line[1], linewidth=line_element.get_linewidth())
zorder = line.get_zorder()
x, y = line.get_data(orig=False)
x, y = np.array(x), np.array(y) # enforce x,y as numpy arrays
xmin, xmax = x.min(), x.max()
ymin, ymax = y.min(), y.max()
xy = np.column_stack([x, y])
if y_avg >= 0:
# if ymax == y_max_global:
# pass
# else:
# alpha *= (ymax/y_max_global)
fill_color = color_positive
linspace = np.linspace(0, alpha, 100)[:, None]
xy = np.vstack([[xmin, ymin], xy, [xmax, ymin], [xmin, ymin]])
else:
# if ymin == y_min_global:
# pass
# else:
# alpha *= (ymin/y_min_global)
fill_color = color_negative
linspace = np.linspace(alpha, 0, 100)[:, None]
xy = np.vstack([[xmin, ymax], xy, [xmax, ymax], [xmin, ymax]])
rgb = mcolors.colorConverter.to_rgb(fill_color)
z = np.empty((100, 1, 4), dtype=float)
z[:, :, :3] = rgb
z[:, :, -1] = linspace
im = ax.imshow(z, aspect='auto',
extent=[xmin, xmax, ymin, ymax],
alpha=alpha_gradientglow,
origin='lower', zorder=zorder)
clip_path = Polygon(xy, facecolor='none', edgecolor='none', closed=True)
ax.add_patch(clip_path)
im.set_clip_path(clip_path)
ax.autoscale(True)
def optimize_lines(x: list, y: list):
y = [list(element) for index, element in groupby(y, lambda a: a >= 0)]
indexes = [0]
for i in y:
indexes.append(len(i) + indexes[-1])
# from https://www.geeksforgeeks.org/python-group-consecutive-elements-by-sign/
x = [x[indexes[i]:indexes[i + 1]] for i, _ in enumerate(indexes) if i != len(indexes) - 1]
for i in range(len(y) - 1):
if y[i][-1] == 0 and y[i + 1][0] == 0:
continue
a = y[i][-1]
b = y[i + 1][0]
diff = abs(a) + abs(b)
a_ = (abs(0 - a)) / diff
b_ = abs(0 - b) / diff
x[i].append(x[i][-1] + a_)
x[i + 1].insert(0, x[i + 1][0] - b_)
y[i].append(0)
y[i + 1].insert(0, 0)
x = [list(i) for i in x]
y = [list(i) for i in y]
# input: x=[1,2,3,4,5], y=[1,2,-5,0,2]
# output: x=[[1, 2, 2.2857142857142856], [2.2857142857142856, 3, 4.0], [4.0, 4, 5]],
# y=[[1, 2, 0], [0, -5, 0], [0, 0, 2]]
return list(x), list(y)
def list_form(x: list[list], y: list[list]):
lst = []
for i in range(len(x)):
lst.append([x[i], y[i]])
return lst
Here I have edited the parameters to include positive_color
and negative_color
, so it gives me an output like this for my specified hex codes:
However what i wanted has been achieved, I shared this code so that it could be incorporated in this repository.
Please add me as a contributor if you decide to add this feature, thanks.
I would also love this feature! If this was added to the repository, that would be great in my opinion!