-
Notifications
You must be signed in to change notification settings - Fork 55
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
When used as backend for matplotlib, GR can't export to svg #178
Comments
As mentioned in this issue, the only way to redirect the GR output is to use the
Could you provide an example how you use GR as a backend for MPL? How did you patch the backend? |
I'm sorry, here some code :) I made a test script using this example as base: https://gr-framework.org/examples/figanim.html You can try GR as a backend for matplotlib and/or as backend for savefig() You'll notice that if you select GR as backend it's not actually used, because def print_svg(self, filename, *args, **kwargs):
gr.beginprint(filename)
self.draw()
gr.endprint() This however is as slow as the default one, and I don't know why. To see what's the actual backend used, I added a couple of debug prints at the beginning of def _switch_canvas_and_return_print_method(self, fmt, backend=None):
"""..."""
canvas = None
if backend is not None:
print(f'using the selected backend: {backend}')
# Return a specific canvas class, if requested.
canvas_class = (
importlib.import_module(cbook._backend_module_name(backend))
.FigureCanvas)
if not hasattr(canvas_class, f"print_{fmt}"):
raise ValueError(
f"The {backend!r} backend does not support {fmt} output")
elif hasattr(self, f"print_{fmt}"):
print(f'using current backend: {self.__class__}')
# Return the current canvas if it supports the requested format.
canvas = self
canvas_class = None # Skip call to switch_backends.
else:
# Return a default canvas for the requested format, if it exists.
canvas_class = get_registered_canvas_class(fmt)
print(f'selected the default backend: {canvas_class}') Here's your modified example import sys
import os
from timeit import default_timer as timer
import numpy as np
import os
import shutil
import argparse
# env
os.environ["GKS_WSTYPE"] = 'svg'
# utility function because gr is easier to write
def backend_name(name: str|None) -> str|None:
if name is not None:
return name.lower() if name.lower() != 'gr' else 'module://gr.matplotlib.backend_gr'
#-------------------------------------------------------------------------------
# args
parser = argparse.ArgumentParser()
parser.add_argument(
"-b", "--backend",
help="Selects a backend for matplotlib",
)
parser.add_argument(
"-s", "--savefig",
help="Selects a backend for savefig(), can be overridden by `--override`",
)
parser.add_argument(
"-o", "--override",
help="The backend selected with `--backend`, if any, will be used for savefig(), "
"otherwise it'll use the default one. "
"If `--savefig` is passed it'll be ignored",
action="store_true",
)
args = parser.parse_args()
backend = backend_name(args.backend)
if backend is not None:
os.environ["MPLBACKEND"] = backend
savefig = backend_name(args.savefig)
override = bool(args.override)
#-------------------------------------------------------------------------------
# output folder
PLOTS_PATH = 'plots'
shutil.rmtree(PLOTS_PATH, ignore_errors=True)
os.mkdir(PLOTS_PATH)
os.chdir(PLOTS_PATH)
#-------------------------------------------------------------------------------
x = np.arange(0, 2 * np.pi, 0.01)
# create an animation using GR
from gr.pygr import plot
tstart = timer()
for i in range(1, 100):
plot(x, np.sin(x + i / 10.0))
if i % 2 == 0:
print('.', end="")
sys.stdout.flush()
fps_gr = int(100 / (timer() - tstart))
print('fps (GR): %4d' % fps_gr)
# create the same animation using matplotlib
import matplotlib
import matplotlib.pyplot as plt
# the current backend, just to be sure
print(f'matplotlib is using: {matplotlib.get_backend()}')
# choose a backend for savefig
# if is overridden uses backend
if not override:
if savefig is not None:
# user selected
backend = savefig
else:
# default
backend = None
tstart = timer()
for i in range(1, 100):
plt.clf()
plt.plot(np.sin(x + i / 10.0))
plt.savefig(f'mpl{i:04d}.svg', backend=backend)
if i % 2 == 0:
print('.', end="")
sys.stdout.flush()
fps_mpl = int(100 / (timer() - tstart))
print('fps (mpl): %4d' % fps_mpl)
print(' speedup: %6.1f' % (float(fps_gr) / fps_mpl)) |
The plain GR example works fine:
Therefore I have to assume that something is suboptimally implemented in Matplotlib. I'll try to find out tomorrow what the problem is. |
Did you find anything? Can I help you in some way? This is the full log of cProfile |
After tests with |
We'll try something else. Anyway, thank you for your time! |
I am developing a desktop application that utilizes Matplotlib for plotting purposes.
To improve performance, I have chosen the GR framework as the backend for Matplotlib, since it's 100 times faster. (nice!)
However, I am currently facing an issue where exporting plots to SVG:
The GR backend does not support svg output
errorWhile researching a solution, I found this old closed issue: gr as backend for matplotlib: Can I save images as png?
Interestingly enough, a response suggested that exporting to SVG format would be an easier alternative, indicating the potential existence of SVG export capability with GR as a backend.
Did I misunderstand something?
OTOH, if this feature is missing, would it be hard to add it?
What would it take to implement it? I'm willing to help, but I know nothing about matplotlib's backends...
Thank you for your attention to this matter
Update:
I patched the backend to save SVGs, but it does it as slow as mpl, so I'm clearly doing something wrong...
The text was updated successfully, but these errors were encountered: