Reputation: 344
is it possible to use a different matplotlib style for each figure I create within a script?
with plt.style.context("style.mpstyle"):
...
can be used to define a temporary custom style in matplotlib. I'm using this in a class, which should handle all my styles:
class Plots():
def __init__(self):
if style == "a":
self.use_style_a()
else:
self.use_style_b()
def use_style_a():
with plt.style.context("style_a.mpstyle"):
self.fig = plt.figure()
[...]
def use_style_b():
with plt.style.context("style_b.mpstyle"):
self.fig = plt.figure()
[...]
Unfortunately, it doesn't really work. Or it's only working 50%... so if I call plt.legend() outside of the initial function call, it's not applying the style from the external style file. So is there a way to apply the figure style to that figure instance, no matter from where I call it?
ImportanceOfBeingErnest gave me the right hint, which I now use in a modified way. Unfortunately, the mpl.style.context()
method doesn't work in this case - I don't know why. But I can just always overwrite the style to use. Probably not the mpl creators intention to use, but it works. Here my code:
import matplotlib.pyplot as plt
class Plot(object):
def __init__(self, name):
self.plot_style = name
func = getattr(self, name)
result = func()
def A(self):
plt.style.use("A.mpstyle")
self.fig = plt.figure()
self.ax = self.fig.add_subplot(1, 1, 1)
# Some styles, labels, ...
def B(self):
plt.style.use("B.mpstyle")
self.fig = plt.figure()
self.ax = self.fig.add_subplot(1, 1, 1)
# Some styles, labels, ...
def __getattribute__(self, name):
if name == "ax":
plt.style.use("{}.mpstyle".format(self.plot_style))
return object.__getattribute__(self, name)
else:
return object.__getattribute__(self, name)
plot_A = Plot("A")
plot_B = Plot("B")
plot_A.ax.plot([1,2,4],[4,2,3])
plot_B.ax.plot([1,2,4],[3,1,6])
plot_A.ax.legend()
plot_B.ax.legend()
# ...
Upvotes: 0
Views: 2784
Reputation: 339705
It think it all depends on how you want to use this class. An option, if you want to create the same plot, but with different styles, would be the following:
import matplotlib.pyplot as plt
class Plots():
def __init__(self, style):
self.set_style(style)
self.plot()
def set_style(self, style):
self.style = "style_{}.mpstyle".format(style)
def plot(self):
with plt.style.context(self.style):
self.fig, self.ax = plt.subplots()
self.ax.plot([1,2,4])
self.ax.legend()
plt.show()
p = Plots("a")
p2 = Plots("b")
I could also imagine that you want to use different functions to do the actual plotting and use a class to manage the styles.
import matplotlib.pyplot as plt
class Plots():
def __init__(self, style="a"):
self.set_style(style)
def set_style(self, style):
self.style = style
def plot(self, func, *args,**kwargs):
with plt.style.context(self.style):
return func(*args,**kwargs)
def myplottingfunction1():
fig, ax = plt.subplots()
ax.plot([1,2,4],[4,2,3], label="mylabel 1")
ax.legend()
def myplottingfunction2(color="red"):
fig, ax = plt.subplots()
ax.scatter([1,2,4],[3,1,6], color=color,label="mylabel 2")
ax.legend()
p = Plots("dark_background").plot(myplottingfunction1)
p2 = Plots("ggplot").plot(myplottingfunction2, color="blue")
plt.show()
The output of this second script would be
Of course the legend can be plotted separately, e.g. like
def myplottingfunction1():
fig, ax = plt.subplots()
ax.plot([1,2,4],[4,2,3], label="mylabel 1")
return ax
def myplottingfunction2(color="red"):
fig, ax = plt.subplots()
ax.scatter([1,2,4],[3,1,6], color=color,label="mylabel 2")
return ax
p = Plots("dark_background")
ax = p.plot(myplottingfunction1)
p2 = Plots("ggplot")
ax2 = p2.plot(myplottingfunction2, color="blue")
# do something else with ax or ax2
p.plot(ax.legend)
p2.plot(ax2.legend)
plt.show()
Upvotes: 2