-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
I am using a custom colorbar (derived from https://gist.github.com/maedoc/b61090021d2a5161c5b9) to show a simple colorbar next to my plots. When exporting the colorbar as SVG (PNG works), the gradient is not shown correctly. The linearGradient tag in the resulting SVG file contains the right steps, but there is some issue with the way it is scaled, probably due to a bad usage of gradientUnits="userSpaceOnUse".
Short description
On SVG export, the linearGradient is not set correctly. This looks like a bad combination of gradientUnits="userSpaceOnUse" and SVG coordinates.
Code to reproduce
This is a minimal working example. Run the script and export the entire scene as SVG.
import numpy as np
import pyqtgraph as pg
from pyqtgraph.graphicsItems.GradientEditorItem import Gradients
class ColorGradient(pg.GraphicsObject):
def __init__(self, cmap, width, height):
pg.GraphicsObject.__init__(self)
# handle args
w, h = width, height
stops, colors = cmap.getStops('float')
smn, spp = stops.min(), stops.ptp()
stops = (stops - stops.min())/stops.ptp()
# setup picture
self.pic = pg.QtGui.QPicture()
p = pg.QtGui.QPainter(self.pic)
# draw bar with gradient following colormap
p.setPen(pg.mkPen('k'))
grad = pg.QtGui.QLinearGradient(w/2.0, 0.0, w/2.0, h*1.0)
for stop, color in zip(stops, colors):
grad.setColorAt(1.0 - stop, pg.QtGui.QColor(*[c for c in color]))
p.setBrush(pg.QtGui.QBrush(grad))
p.drawRect(pg.QtCore.QRectF(0, 0, w, h))
# done
p.end()
def paint(self, p, *args):
# paint underlying mask
p.setPen(pg.QtGui.QColor(255, 255, 255, 0))
p.setBrush(pg.QtGui.QColor(255, 255, 255, 200))
# paint colorbar
p.drawPicture(0, 0, self.pic)
def boundingRect(self):
return pg.QtCore.QRectF(self.pic.boundingRect())
if __name__ == '__main__':
app = pg.mkQApp()
# use less ink
pg.setConfigOption('background', 'w')
pg.setConfigOption('foreground', 'k')
pw = pg.plot()
cm = pg.ColorMap(*zip(*Gradients["viridis"]["ticks"]))
stops, colors = cm.getStops('float')
# make colorbar, placing by hand
cb = ColorGradient(cm, 200, 200)
pw.scene().addItem(cb)
cb.translate(100, 100)
cb.setZValue(100)
app.exec_()Expected behavior
This is a screenshot (PNG export works as well):

Real behavior
This is a screenshot of the exported SVG opened in inkscape:

This is the linearGradient-part in the (larger) SVG file. Note the usage of gradientUnits="userSpaceOnUse". If you removed this and put all corrdinates in % everywhere, the linearGradient is reproduced correctly.
<linearGradient gradientUnits="userSpaceOnUse" x1="100" y1="0" x2="100" y2="200" id="gradient1">
<stop offset="0" stop-color="#fde724" stop-opacity="1"/>
<stop offset="0.25" stop-color="#5ec961" stop-opacity="1"/>
<stop offset="0.5" stop-color="#20908c" stop-opacity="1"/>
<stop offset="0.75" stop-color="#3a528b" stop-opacity="1"/>
<stop offset="1" stop-color="#440154" stop-opacity="1"/>
</linearGradient>Tested environment(s)
- PyQtGraph version: 0.12.1
- Qt Python binding: 'PyQt5 5.15.1 Qt 5.15.1'
- Python version: 3.8.5 (default, May 27 2021, 13:30:53)
- NumPy version: '1.18.5'
- Operating system: Ubuntu 20.04
- Installation method: pip