class SVGExporter(Exporter):
    Name = "Scalable Vector Graphics (SVG)"
    allowCopy = True

    def __init__(self, item):
        Exporter.__init__(self, item)
        # tr = self.getTargetRect()
        self.params = Parameter(
            name="params",
            type="group",
            children=[
                # {'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)},
                # {'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)},
                # {'name': 'viewbox clipping', 'type': 'bool', 'value': True},
                # {'name': 'normalize coordinates', 'type': 'bool', 'value': True},
                # {'name': 'normalize line width', 'type': 'bool', 'value': True},
            ],
        )
        # self.params.param('width').sigValueChanged.connect(self.widthChanged)
        # self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param("height").setValue(self.params["width"] * ar,
                                             blockSignal=self.heightChanged)

    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param("width").setValue(self.params["height"] * ar,
                                            blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None, toBytes=False, copy=False):
        if toBytes is False and copy is False and fileName is None:
            self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)")
            return

        ## Qt's SVG generator is not complete. (notably, it lacks clipping)
        ## Instead, we will use Qt to generate SVG for each item independently,
        ## then manually reconstruct the entire document.
        xml = generateSvg(self.item)

        if toBytes:
            return xml.encode("UTF-8")
        elif copy:
            md = QtCore.QMimeData()
            md.setData("image/svg+xml", QtCore.QByteArray(xml.encode("UTF-8")))
            QtGui.QApplication.clipboard().setMimeData(md)
        else:
            with open(fileName, "wb") as fh:
                fh.write(asUnicode(xml).encode("utf-8"))
Ejemplo n.º 2
0
class ImageExporter(Exporter):
    Name = "Image File (PNG, TIF, JPG, ...)"
    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        
        self.params = Parameter(name='params', type='group', children=[
            {'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None)},
            {'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None)},
            {'name': 'antialias', 'type': 'bool', 'value': True},
            {'name': 'background', 'type': 'color', 'value': (0,0,0,255)},
        ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)
        
    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
        
    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
        
    def parameters(self):
        return self.params
    
    def export(self, fileName=None):
        if fileName is None:
            filter = ["*."+str(f) for f in QtGui.QImageWriter.supportedImageFormats()]
            preferred = ['*.png', '*.tif', '*.jpg']
            for p in preferred[::-1]:
                if p in filter:
                    filter.remove(p)
                    filter.insert(0, p)
            self.fileSaveDialog(filter=filter)
            return
            
        targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
        sourceRect = self.getSourceRect()
        #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
        #self.png.fill(pyqtgraph.mkColor(self.params['background']))
        bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte)
        color = self.params['background']
        bg[:,:,0] = color.blue()
        bg[:,:,1] = color.green()
        bg[:,:,2] = color.red()
        bg[:,:,3] = color.alpha()
        self.png = pg.makeQImage(bg, alpha=True)
        painter = QtGui.QPainter(self.png)
        try:
            self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background']})
            self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
        finally:
            self.setExportMode(False)
        self.png.save(fileName)
        painter.end()
        
        
Ejemplo n.º 3
0
class SVGExporter(Exporter):
    Name = "Scalable Vector Graphics (SVG)"
    allowCopy = True

    def __init__(self, item):
        Exporter.__init__(self, item)
        #tr = self.getTargetRect()
        self.params = Parameter(name='params', type='group', children=[
            #{'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)},
            #{'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)},
            #{'name': 'viewbox clipping', 'type': 'bool', 'value': True},
            #{'name': 'normalize coordinates', 'type': 'bool', 'value': True},
            #{'name': 'normalize line width', 'type': 'bool', 'value': True},
        ])
        #self.params.param('width').sigValueChanged.connect(self.widthChanged)
        #self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)

    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None, toBytes=False, copy=False):
        if toBytes is False and copy is False and fileName is None:
            self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)")
            return

        ## Qt's SVG generator is not complete. (notably, it lacks clipping)
        ## Instead, we will use Qt to generate SVG for each item independently,
        ## then manually reconstruct the entire document.
        xml = generateSvg(self.item)

        if toBytes:
            return xml.encode('UTF-8')
        elif copy:
            md = QtCore.QMimeData()
            md.setData('image/svg+xml', QtCore.QByteArray(xml.encode('UTF-8')))
            QtGui.QApplication.clipboard().setMimeData(md)
        else:
            with open(fileName, 'wb') as fh:
                fh.write(asUnicode(xml).encode('utf-8'))
Ejemplo n.º 4
0
class PrintExporter(Exporter):
    Name = "Printer"
    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        self.params = Parameter(name='params', type='group', children=[
            {'name': 'width', 'type': 'float', 'value': 0.1, 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
            {'name': 'height', 'type': 'float', 'value': (0.1 * tr.height()) / tr.width(), 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
        ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
        
    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
        
    def parameters(self):
        return self.params
    
    def export(self, fileName=None):
        printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
        dialog = QtGui.QPrintDialog(printer)
        dialog.setWindowTitle("Print Document")
        if dialog.exec_() != QtGui.QDialog.Accepted:
            return;
            
        #dpi = QtGui.QDesktopWidget().physicalDpiX()
        
        #self.svg.setSize(QtCore.QSize(100,100))
        #self.svg.setResolution(600)
        #res = printer.resolution()
        sr = self.getSourceRect()
        #res = sr.width() * .4 / (self.params['width'] * 100 / 2.54)
        res = QtGui.QDesktopWidget().physicalDpiX()
        printer.setResolution(res)
        rect = printer.pageRect()
        center = rect.center()
        h = self.params['height'] * res * 100. / 2.54
        w = self.params['width'] * res * 100. / 2.54
        x = center.x() - w/2.
        y = center.y() - h/2.
        
        targetRect = QtCore.QRect(x, y, w, h)
        sourceRect = self.getSourceRect()
        painter = QtGui.QPainter(printer)
        try:
            self.setExportMode(True, {'painter': painter})
            self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
        finally:
            self.setExportMode(False)
        painter.end()
Ejemplo n.º 5
0
class VideoExporter(Exporter):
    """
    A custom class that allows exporting pyqtgraph elements as video.

    Choosing this as an export option opens a new window which displays the part of the program being recorded.
    """
    Name = "Video file"
    allowCopy = True

    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        if isinstance(item, QGraphicsItem):
            scene = item.scene()
        else:
            scene = item
        bgbrush = scene.views()[0].backgroundBrush()
        bg = bgbrush.color()
        if bgbrush.style() == QtCore.Qt.NoBrush:
            bg.setAlpha(0)

        self.item = item

        self.params = Parameter(name='params', type='group', children=[
            {'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None)},
            {'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None)},
            {'name': 'antialias', 'type': 'bool', 'value': True},
            {'name': 'background', 'type': 'color', 'value': bg},
        ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.height()) / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)

    def heightChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.width()) / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None, toBytes=False, copy=False):
        area = self.getTargetRect()
        point = QtCore.QPoint(area.left(), area.top())
        if isinstance(self.item, GraphicsScene):
            global_point = self.item.parent().mapToGlobal(point)
            w, h = self.params["width"], self.params["height"]
        else:
            global_point = self.item.scene().parent().mapToGlobal(point)
            w, h = self.params["width"] + 10, self.params["height"] + 10

        self.video = VideoPlayer(w, h, global_point)
        self.video.show()
Ejemplo n.º 6
0
class PrintExporter(Exporter):
    Name = "Printer"
    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        self.params = Parameter(name='params', type='group', children=[
            {'name': 'width', 'type': 'float', 'value': 0.1, 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
            {'name': 'height', 'type': 'float', 'value': (0.1 * tr.height()) / tr.width(), 'limits': (0, None), 'suffix': 'm', 'siPrefix': True},
        ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
        
    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
        
    def parameters(self):
        return self.params
    
    def export(self, fileName=None):
        printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
        dialog = QtGui.QPrintDialog(printer)
        dialog.setWindowTitle("Print Document")
        if dialog.exec_() != QtGui.QDialog.Accepted:
            return;
            
        #self.svg.setSize(QtCore.QSize(100,100))
        #self.svg.setResolution(600)
        res = printer.resolution()
        rect = printer.pageRect()
        center = rect.center()
        h = self.params['height'] * res * 100. / 2.54
        w = self.params['width'] * res * 100. / 2.54
        x = center.x() - w/2.
        y = center.y() - h/2.
        
        targetRect = QtCore.QRect(x, y, w, h)
        sourceRect = self.getSourceRect()
        painter = QtGui.QPainter(printer)
        try:
            self.setExportMode(True)
            self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect)
        finally:
            self.setExportMode(False)
        painter.end()
Ejemplo n.º 7
0
class PQG_ImageExporter(Exporter):
    Name = "Working Image Exporter (PNG, TIF, JPG, ...)"
    allowCopy = True

    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        if isinstance(item, QtGui.QGraphicsItem):
            scene = item.scene()
        else:
            scene = item
        # scene.views()[0].backgroundBrush()
        bgbrush = pg.mkBrush('w')
        bg = bgbrush.color()
        if bgbrush.style() == QtCore.Qt.NoBrush:
            bg.setAlpha(0)

        self.params = Parameter(name='params',
                                type='group',
                                children=[
                                    {
                                        'name': 'width',
                                        'type': 'int',
                                        'value': tr.width(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'height',
                                        'type': 'int',
                                        'value': tr.height(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'antialias',
                                        'type': 'bool',
                                        'value': True
                                    },
                                    {
                                        'name': 'background',
                                        'type': 'color',
                                        'value': bg
                                    },
                                ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.height()) / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar,
                                             blockSignal=self.heightChanged)

    def heightChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.width()) / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar,
                                            blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None, toBytes=False, copy=False):
        if fileName is None and not toBytes and not copy:
            if USE_PYSIDE:
                filter = [
                    "*." + str(f)
                    for f in QtGui.QImageWriter.supportedImageFormats()
                ]
            else:
                filter = [
                    "*." + bytes(f).decode('utf-8')
                    for f in QtGui.QImageWriter.supportedImageFormats()
                ]
            preferred = ['*.png', '*.tif', '*.jpg']
            for p in preferred[::-1]:
                if p in filter:
                    filter.remove(p)
                    filter.insert(0, p)
            self.fileSaveDialog(filter=filter)
            return

        targetRect = QtCore.QRect(0, 0, self.params['width'],
                                  self.params['height'])
        sourceRect = self.getSourceRect()

        #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
        # self.png.fill(pyqtgraph.mkColor(self.params['background']))
        w, h = self.params['width'], self.params['height']
        if w == 0 or h == 0:
            raise Exception(
                "Cannot export image with size=0 (requested export size is %dx%d)"
                % (w, h))
        bg = np.empty(
            (int(self.params['width']), int(self.params['height']), 4),
            dtype=np.ubyte)
        color = self.params['background']
        bg[:, :, 0] = color.blue()
        bg[:, :, 1] = color.green()
        bg[:, :, 2] = color.red()
        bg[:, :, 3] = color.alpha()
        self.png = fn.makeQImage(bg, alpha=True)

        # set resolution of image:
        origTargetRect = self.getTargetRect()
        resolutionScale = targetRect.width() / origTargetRect.width()
        #self.png.setDotsPerMeterX(self.png.dotsPerMeterX() * resolutionScale)
        #self.png.setDotsPerMeterY(self.png.dotsPerMeterY() * resolutionScale)

        painter = QtGui.QPainter(self.png)
        #dtr = painter.deviceTransform()
        try:
            self.setExportMode(
                True, {
                    'antialias': self.params['antialias'],
                    'background': self.params['background'],
                    'painter': painter,
                    'resolutionScale': resolutionScale
                })
            painter.setRenderHint(QtGui.QPainter.Antialiasing,
                                  self.params['antialias'])
            self.getScene().render(painter, QtCore.QRectF(targetRect),
                                   QtCore.QRectF(sourceRect))
        finally:
            self.setExportMode(False)
        painter.end()

        if copy:
            QtGui.QApplication.clipboard().setImage(self.png)
        elif toBytes:
            return self.png
        else:
            self.png.save(fileName)
Ejemplo n.º 8
0
class ImageExporter(Exporter):
    Name = "Image File (PNG, TIF, JPG, ...)"
    allowCopy = True

    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        if isinstance(item, QtGui.QGraphicsItem):
            scene = item.scene()
        else:
            scene = item
        bgbrush = scene.views()[0].backgroundBrush()
        bg = bgbrush.color()
        if bgbrush.style() == QtCore.Qt.NoBrush:
            bg.setAlpha(0)

        self.params = Parameter(
            name="params",
            type="group",
            children=[
                {"name": "width", "type": "int", "value": tr.width(), "limits": (0, None)},
                {"name": "height", "type": "int", "value": tr.height(), "limits": (0, None)},
                {"name": "antialias", "type": "bool", "value": True},
                {"name": "background", "type": "color", "value": bg},
            ],
        )
        self.params.param("width").sigValueChanged.connect(self.widthChanged)
        self.params.param("height").sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.height()) / sr.width()
        self.params.param("height").setValue(self.params["width"] * ar, blockSignal=self.heightChanged)

    def heightChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.width()) / sr.height()
        self.params.param("width").setValue(self.params["height"] * ar, blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None, toBytes=False, copy=False):
        if fileName is None and not toBytes and not copy:
            if USE_PYSIDE:
                filter = ["*." + str(f) for f in QtGui.QImageWriter.supportedImageFormats()]
            else:
                filter = ["*." + bytes(f).decode("utf-8") for f in QtGui.QImageWriter.supportedImageFormats()]
            preferred = ["*.png", "*.tif", "*.jpg"]
            for p in preferred[::-1]:
                if p in filter:
                    filter.remove(p)
                    filter.insert(0, p)
            self.fileSaveDialog(filter=filter)
            return

        targetRect = QtCore.QRect(0, 0, self.params["width"], self.params["height"])
        sourceRect = self.getSourceRect()

        # self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
        # self.png.fill(pyqtgraph.mkColor(self.params['background']))
        bg = np.empty((self.params["width"], self.params["height"], 4), dtype=np.ubyte)
        color = self.params["background"]
        bg[:, :, 0] = color.blue()
        bg[:, :, 1] = color.green()
        bg[:, :, 2] = color.red()
        bg[:, :, 3] = color.alpha()
        self.png = pg.makeQImage(bg, alpha=True)

        ## set resolution of image:
        origTargetRect = self.getTargetRect()
        resolutionScale = targetRect.width() / origTargetRect.width()
        # self.png.setDotsPerMeterX(self.png.dotsPerMeterX() * resolutionScale)
        # self.png.setDotsPerMeterY(self.png.dotsPerMeterY() * resolutionScale)

        painter = QtGui.QPainter(self.png)
        # dtr = painter.deviceTransform()
        try:
            self.setExportMode(
                True,
                {
                    "antialias": self.params["antialias"],
                    "background": self.params["background"],
                    "painter": painter,
                    "resolutionScale": resolutionScale,
                },
            )
            painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params["antialias"])
            self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
        finally:
            self.setExportMode(False)
        painter.end()

        if copy:
            QtGui.QApplication.clipboard().setImage(self.png)
        elif toBytes:
            return self.png
        else:
            self.png.save(fileName)
Ejemplo n.º 9
0
class PytplotExporter(pg.exporters.ImageExporter):
    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        if isinstance(item, QtGui.QGraphicsItem):
            scene = item.scene()
        else:
            scene = item
        # CHANGE: Used to be scene.views()[0].backgroundBrush()
        # That wasn't how to access the background of a GraphicsLayout object
        bgbrush = scene.backgroundBrush()
        bg = bgbrush.color()
        if bgbrush.style() == QtCore.Qt.NoBrush:
            bg.setAlpha(0)

        self.params = Parameter(name='params',
                                type='group',
                                children=[
                                    {
                                        'name': 'width',
                                        'type': 'int',
                                        'value': tr.width(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'height',
                                        'type': 'int',
                                        'value': tr.height(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'antialias',
                                        'type': 'bool',
                                        'value': True
                                    },
                                    {
                                        'name': 'background',
                                        'type': 'color',
                                        'value': bg
                                    },
                                ])

        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def export(self, fileName=None, toBytes=False, copy=False):
        if fileName is None and not toBytes and not copy:
            if pg.Qt.USE_PYSIDE:
                filter = [
                    "*." + str(f)
                    for f in QtGui.QImageWriter.supportedImageFormats()
                ]
            else:
                filter = [
                    "*." + bytes(f).decode('utf-8')
                    for f in QtGui.QImageWriter.supportedImageFormats()
                ]
            preferred = ['*.png', '*.tif', '*.jpg']
            for p in preferred[::-1]:
                if p in filter:
                    filter.remove(p)
                    filter.insert(0, p)
            self.fileSaveDialog(filter=filter)
            return

        targetRect = QtCore.QRect(0, 0, self.params['width'],
                                  self.params['height'])
        sourceRect = self.getSourceRect()

        # self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
        # self.png.fill(pyqtgraph.mkColor(self.params['background']))
        w, h = self.params['width'], self.params['height']
        if w == 0 or h == 0:
            raise Exception(
                "Cannot export image with size=0 (requested export size is %dx%d)"
                % (w, h))
        bg = np.empty(
            (int(self.params['width']), int(self.params['height']), 4),
            dtype=np.ubyte)
        color = self.params['background']
        bg[:, :, 0] = color.blue()
        bg[:, :, 1] = color.green()
        bg[:, :, 2] = color.red()
        bg[:, :, 3] = color.alpha()
        self.png = fn.makeQImage(bg, alpha=True)

        # set resolution of image:
        origTargetRect = self.getTargetRect()
        resolutionScale = targetRect.width() / origTargetRect.width()

        painter = QtGui.QPainter(self.png)
        # dtr = painter.deviceTransform()
        try:
            self.setExportMode(
                True, {
                    'antialias': self.params['antialias'],
                    'background': self.params['background'],
                    'painter': painter,
                    'resolutionScale': resolutionScale
                })
            painter.setRenderHint(QtGui.QPainter.Antialiasing,
                                  self.params['antialias'])
            # CHANGE: Rendering the scence twice onto the QImage.  The first time, make it one pixel in size.
            # Next, render the full thing.  No idea why we need to render is twice, but we do.
            self.getScene().render(painter, QtCore.QRectF(0, 0, 1, 1),
                                   QtCore.QRectF(0, 0, 1, 1))
            self.getScene().render(painter, QtCore.QRectF(targetRect),
                                   QtCore.QRectF(sourceRect))
        finally:
            self.setExportMode(False)
        painter.end()

        if copy:
            QtGui.QApplication.clipboard().setImage(self.png)
        elif toBytes:
            return self.png
        else:
            self.png.save(fileName)

    def getPaintItems(self, root=None):
        """Return a list of all items that should be painted in the correct order."""
        if root is None:
            root = self.item
        preItems = []
        postItems = []
        if isinstance(root, QtGui.QGraphicsScene):
            childs = [i for i in root.items() if i.parentItem() is None]
            rootItem = []
        else:
            # CHANGE: For GraphicsLayouts, there is no function for childItems(), so I just
            # replaced it with .items()
            try:
                childs = root.childItems()
            except:
                childs = root.items()
            rootItem = [root]
        childs.sort(key=lambda a: a.zValue())
        while len(childs) > 0:
            ch = childs.pop(0)
            tree = self.getPaintItems(ch)

            if int(ch.flags() & ch.ItemStacksBehindParent) > 0 or (
                    ch.zValue() < 0 and
                    int(ch.flags() & ch.ItemNegativeZStacksBehindParent) > 0):
                preItems.extend(tree)
            else:
                postItems.extend(tree)
        return preItems + rootItem + postItems

    def getTargetRect(self):
        # CHANGE: Used to return self.item.sceneBoundingRect().  GraphicsLayouts don't have a
        # sceneBoundingRect(), but they have a rect() which appears to work just as well.
        return self.item.rect()

    def getSourceRect(self):
        # CHANGE: Used to return self.item.mapRectToDevice(self.item.boundingRect()).  GraphicsLayouts don't have a
        # sceneBoundingRect() OR a mapRectToDevice, but they have a rect() which appears to work just as well.
        return self.item.rect()
Ejemplo n.º 10
0
class SVGExporter(Exporter):
    Name = "Scalable Vector Graphics (SVG)"
    allowCopy=True
    
    def __init__(self, item):
        Exporter.__init__(self, item)
        #tr = self.getTargetRect()
        self.params = Parameter(name='params', type='group', children=[
            #{'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)},
            #{'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)},
            #{'name': 'viewbox clipping', 'type': 'bool', 'value': True},
            #{'name': 'normalize coordinates', 'type': 'bool', 'value': True},
            #{'name': 'normalize line width', 'type': 'bool', 'value': True},
        ])
        #self.params.param('width').sigValueChanged.connect(self.widthChanged)
        #self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
        
    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
        
    def parameters(self):
        return self.params
    
    def export(self, fileName=None, toBytes=False, copy=False):
        if toBytes is False and copy is False and fileName is None:
            self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)")
            return
        #self.svg = QtSvg.QSvgGenerator()
        #self.svg.setFileName(fileName)
        #dpi = QtGui.QDesktopWidget().physicalDpiX()
        ### not really sure why this works, but it seems to be important:
        #self.svg.setSize(QtCore.QSize(self.params['width']*dpi/90., self.params['height']*dpi/90.))
        #self.svg.setResolution(dpi)
        ##self.svg.setViewBox()
        #targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
        #sourceRect = self.getSourceRect()
        
        #painter = QtGui.QPainter(self.svg)
        #try:
            #self.setExportMode(True)
            #self.render(painter, QtCore.QRectF(targetRect), sourceRect)
        #finally:
            #self.setExportMode(False)
        #painter.end()

        ## Workaround to set pen widths correctly
        #data = open(fileName).readlines()
        #for i in range(len(data)):
            #line = data[i]
            #m = re.match(r'(<g .*)stroke-width="1"(.*transform="matrix\(([^\)]+)\)".*)', line)
            #if m is not None:
                ##print "Matched group:", line
                #g = m.groups()
                #matrix = list(map(float, g[2].split(',')))
                ##print "matrix:", matrix
                #scale = max(abs(matrix[0]), abs(matrix[3]))
                #if scale == 0 or scale == 1.0:
                    #continue
                #data[i] = g[0] + ' stroke-width="%0.2g" ' % (1.0/scale) + g[1] + '\n'
                ##print "old line:", line
                ##print "new line:", data[i]
        #open(fileName, 'w').write(''.join(data))
        
        ## Qt's SVG generator is not complete. (notably, it lacks clipping)
        ## Instead, we will use Qt to generate SVG for each item independently,
        ## then manually reconstruct the entire document.
        xml = generateSvg(self.item)
        
        if toBytes:
            return xml.encode('UTF-8')
        elif copy:
            md = QtCore.QMimeData()
            md.setData('image/svg+xml', QtCore.QByteArray(xml.encode('UTF-8')))
            QtGui.QApplication.clipboard().setMimeData(md)
        else:
            with open(fileName, 'wb') as fh:
                fh.write(asUnicode(xml).encode('utf-8'))
Ejemplo n.º 11
0
class ImageExporter(Exporter):
    Name = "Image File (PNG, TIF, JPG, ...)"
    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        if isinstance(item, QtGui.QGraphicsItem):
            scene = item.scene()
        else:
            scene = item
        bg = scene.views()[0].backgroundBrush().color()
        self.params = Parameter(name='params', type='group', children=[
            {'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None)},
            {'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None)},
            {'name': 'antialias', 'type': 'bool', 'value': True},
            {'name': 'background', 'type': 'color', 'value': bg},
        ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)
        
    def widthChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.height()) / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
        
    def heightChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.width()) / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
        
    def parameters(self):
        return self.params
    
    def export(self, fileName=None):
        if fileName is None:
            filter = ["*."+str(f) for f in QtGui.QImageWriter.supportedImageFormats()]
            preferred = ['*.png', '*.tif', '*.jpg']
            for p in preferred[::-1]:
                if p in filter:
                    filter.remove(p)
                    filter.insert(0, p)
            self.fileSaveDialog(filter=filter)
            return
            
        targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
        sourceRect = self.getSourceRect()
        
        
        #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
        #self.png.fill(pyqtgraph.mkColor(self.params['background']))
        bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte)
        color = self.params['background']
        bg[:,:,0] = color.blue()
        bg[:,:,1] = color.green()
        bg[:,:,2] = color.red()
        bg[:,:,3] = color.alpha()
        self.png = pg.makeQImage(bg, alpha=True)
        
        ## set resolution of image:
        origTargetRect = self.getTargetRect()
        resolutionScale = targetRect.width() / origTargetRect.width()
        #self.png.setDotsPerMeterX(self.png.dotsPerMeterX() * resolutionScale)
        #self.png.setDotsPerMeterY(self.png.dotsPerMeterY() * resolutionScale)
        
        painter = QtGui.QPainter(self.png)
        #dtr = painter.deviceTransform()
        try:
            self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background'], 'painter': painter, 'resolutionScale': resolutionScale})
            painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias'])
            self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect))
        finally:
            self.setExportMode(False)
        painter.end()
        self.png.save(fileName)
        
        
Ejemplo n.º 12
0
class GraphExporter(Exporter):

    Name = "Image File (PNG, TIF, JPG, ...)"
    allowCopy = True

    #Initialize the exporter
    def __init__(self, item):

        Exporter.__init__(self, item)
        tr = self.getTargetRect()

        if isinstance(item, QtGui.QGraphicsItem):
            scene = item.scene()

        else:
            scene = item

        bgbrush = scene.views()[0].backgroundBrush()
        bg = bgbrush.color()

        if bgbrush.style() == QtCore.Qt.NoBrush:
            bg.setAlpha(0)

        self.params = Parameter(name='params',
                                type='group',
                                children=[
                                    {
                                        'name': 'width',
                                        'type': 'int',
                                        'value': tr.width(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'height',
                                        'type': 'int',
                                        'value': tr.height(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'antialias',
                                        'type': 'bool',
                                        'value': True
                                    },
                                    {
                                        'name': 'background',
                                        'type': 'color',
                                        'value': bg
                                    },
                                ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    #Adjust the height relative to the width if the width changes
    def widthChanged(self):

        sr = self.getSourceRect()
        ar = float(sr.height()) / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar,
                                             blockSignal=self.heightChanged)

    #Adjust the width relative to the height if the width changes
    def heightChanged(self):

        sr = self.getSourceRect()
        ar = float(sr.width()) / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar,
                                            blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None, toBytes=False, copy=False):

        if fileName is None and not toBytes and not copy:

            if USE_PYSIDE:
                filter = [
                    "*." + str(f)
                    for f in QtGui.QImageWriter.supportedImageFormats()
                ]

            else:
                filter = [
                    "*." + bytes(f).decode('utf-8')
                    for f in QtGui.QImageWriter.supportedImageFormats()
                ]
            preferred = ['*.png', '*.tif', '*.jpg']

            for p in preferred[::-1]:

                if p in filter:
                    filter.remove(p)
                    filter.insert(0, p)

            self.fileSaveDialog(filter=filter)
            return

        targetRect = QtCore.QRect(0, 0, self.params['width'],
                                  self.params['height'])
        sourceRect = self.getSourceRect()

        w, h = self.params['width'], self.params['height']

        if w == 0 or h == 0:
            raise Exception(
                "Cannot export image with size=0 (requested export size is %dx%d)"
                % (w, h))

        #BEFORE
        #bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte)

        #AFTER
        bgSize = ((int(self.params['width']), int(self.params['height']), 4))
        bg = np.empty(bgSize, dtype=np.ubyte)

        #... I have no idea why that fixes it, I just guessed around and googled for 3 hours until it worked.
        #https://groups.google.com/forum/?nomobile=true#!topic/pyqtgraph/4jiAPUpLpF4
        #Above link led me on the right track to fixing it but for some reason I also had to declare bgSize separately?

        color = self.params['background']
        bg[:, :, 0] = color.blue()
        bg[:, :, 1] = color.green()
        bg[:, :, 2] = color.red()
        bg[:, :, 3] = color.alpha()
        self.png = fn.makeQImage(bg, alpha=True)

        ## set resolution of image:
        origTargetRect = self.getTargetRect()
        resolutionScale = targetRect.width() / origTargetRect.width()

        painter = QtGui.QPainter(self.png)

        try:
            self.setExportMode(
                True, {
                    'antialias': self.params['antialias'],
                    'background': self.params['background'],
                    'painter': painter,
                    'resolutionScale': resolutionScale
                })
            painter.setRenderHint(QtGui.QPainter.Antialiasing,
                                  self.params['antialias'])
            self.getScene().render(painter, QtCore.QRectF(targetRect),
                                   QtCore.QRectF(sourceRect))

        finally:
            self.setExportMode(False)
        painter.end()

        if copy:
            QtGui.QApplication.clipboard().setImage(self.png)

        elif toBytes:
            return self.png

        else:
            self.png.save(fileName)
Ejemplo n.º 13
0
class MovieExporter(Exporter):
    Name = "Movie File (MPEG, MP4)"
    allowCopy = False

    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        if isinstance(item, QtGui.QGraphicsItem):
            scene = item.scene()
        else:
            scene = item
        bgbrush = scene.views()[0].backgroundBrush()
        bg = bgbrush.color()
        if bgbrush.style() == QtCore.Qt.NoBrush:
            bg.setAlpha(0)

        # Search for DaXView
        wid = self.item.getViewWidget()
        while wid != None and not isinstance(wid, DaXView.DaXView):
            wid = wid.parent()
        self.daxview = wid

        self.params = Parameter(name='params',
                                type='group',
                                children=[
                                    {
                                        'name': 'width',
                                        'type': 'int',
                                        'value': tr.width(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'height',
                                        'type': 'int',
                                        'value': tr.height(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'frame rate',
                                        'type': 'int',
                                        'value': 20,
                                        'limits': (1, 60)
                                    },
                                    {
                                        'name': 'antialias',
                                        'type': 'bool',
                                        'value': True
                                    },
                                    {
                                        'name': 'background',
                                        'type': 'color',
                                        'value': bg
                                    },
                                ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.height()) / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar,
                                             blockSignal=self.heightChanged)

    def heightChanged(self):
        sr = self.getSourceRect()
        ar = float(sr.width()) / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar,
                                            blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None, toBytes=False, copy=False):
        # Can only export video from DaXView
        if self.daxview == None:
            return
        # Can only write to video
        if toBytes:
            return []

        # Get filename from user (the fileSaveDialog function calls export after finishing)
        if fileName is None:
            self.fileSaveDialog(filter=['*.mpeg', '*.mp4'])
            return
        if fileName.endswith('.mpeg') == False and fileName.endswith(
                '.mp4') == False:
            fileName = fileName + '.mpeg'
        # Get directory where video should go
        dirName = os.path.dirname(fileName)

        # Play entire sequence and store to temporary PNG files
        progress = QtGui.QProgressDialog('Exporting movie...', 'Abort', 0,
                                         int(self.daxview.data.shape[0] * 1.1))
        for i in range(self.daxview.data.shape[0]):
            # Set current frame
            self.daxview.setCurrentIndex(i)
            if i >= self.daxview.data.shape[0]:
                progress.setLabelText('Generating video...')
            # Export to png image
            targetRect = QtCore.QRect(0, 0, self.params['width'],
                                      self.params['height'])
            sourceRect = self.getSourceRect()

            #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
            #self.png.fill(pyqtgraph.mkColor(self.params['background']))
            w, h = self.params['width'], self.params['height']
            if w == 0 or h == 0:
                raise Exception(
                    "Cannot export image with size=0 (requested export size is %dx%d)"
                    % (w, h))
            bg = np.empty((self.params['width'], self.params['height'], 4),
                          dtype=np.ubyte)
            color = self.params['background']
            bg[:, :, 0] = color.blue()
            bg[:, :, 1] = color.green()
            bg[:, :, 2] = color.red()
            bg[:, :, 3] = color.alpha()
            self.png = fn.makeQImage(bg, alpha=False)

            ## set resolution of image:
            origTargetRect = self.getTargetRect()
            resolutionScale = targetRect.width() / origTargetRect.width()

            painter = QtGui.QPainter(self.png)
            #dtr = painter.deviceTransform()
            try:
                self.setExportMode(
                    True, {
                        'antialias': self.params['antialias'],
                        'background': self.params['background'],
                        'painter': painter,
                        'resolutionScale': resolutionScale
                    })
                painter.setRenderHint(QtGui.QPainter.Antialiasing,
                                      self.params['antialias'])
                self.getScene().render(painter, QtCore.QRectF(targetRect),
                                       QtCore.QRectF(sourceRect))
            finally:
                self.setExportMode(False)
            painter.end()
            # Send to png file
            pngFile = dirName + '/temp_' + '{:03d}'.format(i) + '.png'
            self.png.save(pngFile)
            progress.setValue(i)
            QtGui.QApplication.processEvents()
            if progress.wasCanceled():
                # Clean-up PNGs
                rmfiles = glob.glob('temp_*.png')
                for f in rmfiles:
                    os.remove(f)
                progress.close()
                return
        progress.close()

        # Convert PNGs to movie with FFMPEG
        if fileName.endswith('mpeg'):
            codec = 'mpeg2video'
        else:
            codec = 'libx264'
        sp.call([
            'ffmpeg', '-r',
            str(self.params.param('frame rate').value()), '-i',
            dirName + '/temp_%03d.png', '-b:v', '1000K', '-c:v', codec,
            '-vframes',
            str(self.daxview.data.shape[0]), '-y', fileName
        ])
        # Clean-up PNGs
        rmfiles = glob.glob(dirName + '/temp_*.png')
        for f in rmfiles:
            os.remove(f)
        return
Ejemplo n.º 14
0
class ImageExporter(Exporter):
    Name = "Image File (PNG, TIF, JPG, ...)"

    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()

        self.params = Parameter(name='params',
                                type='group',
                                children=[
                                    {
                                        'name': 'width',
                                        'type': 'int',
                                        'value': tr.width(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'height',
                                        'type': 'int',
                                        'value': tr.height(),
                                        'limits': (0, None)
                                    },
                                    {
                                        'name': 'antialias',
                                        'type': 'bool',
                                        'value': True
                                    },
                                    {
                                        'name': 'background',
                                        'type': 'color',
                                        'value': (0, 0, 0, 255)
                                    },
                                ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar,
                                             blockSignal=self.heightChanged)

    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar,
                                            blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None):
        if fileName is None:
            filter = [
                "*." + str(f)
                for f in QtGui.QImageWriter.supportedImageFormats()
            ]
            preferred = ['*.png', '*.tif', '*.jpg']
            for p in preferred[::-1]:
                if p in filter:
                    filter.remove(p)
                    filter.insert(0, p)
            self.fileSaveDialog(filter=filter)
            return

        targetRect = QtCore.QRect(0, 0, self.params['width'],
                                  self.params['height'])
        sourceRect = self.getSourceRect()
        #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32)
        #self.png.fill(pyqtgraph.mkColor(self.params['background']))
        bg = np.empty((self.params['width'], self.params['height'], 4),
                      dtype=np.ubyte)
        color = self.params['background']
        bg[:, :, 0] = color.blue()
        bg[:, :, 1] = color.green()
        bg[:, :, 2] = color.red()
        bg[:, :, 3] = color.alpha()
        self.png = pg.makeQImage(bg, alpha=True)
        painter = QtGui.QPainter(self.png)
        try:
            self.setExportMode(
                True, {
                    'antialias': self.params['antialias'],
                    'background': self.params['background']
                })
            painter.setRenderHint(QtGui.QPainter.Antialiasing,
                                  self.params['antialias'])
            self.getScene().render(painter, QtCore.QRectF(targetRect),
                                   sourceRect)
        finally:
            self.setExportMode(False)
        self.png.save(fileName)
        painter.end()
Ejemplo n.º 15
0
class SVGExporter(Exporter):
    Name = "Scalable Vector Graphics (SVG)"
    allowCopy = True

    def __init__(self, item):
        Exporter.__init__(self, item)
        #tr = self.getTargetRect()
        self.params = Parameter(
            name='params',
            type='group',
            children=[
                #{'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)},
                #{'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)},
                #{'name': 'viewbox clipping', 'type': 'bool', 'value': True},
                #{'name': 'normalize coordinates', 'type': 'bool', 'value': True},
                #{'name': 'normalize line width', 'type': 'bool', 'value': True},
            ])
        #self.params.param('width').sigValueChanged.connect(self.widthChanged)
        #self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar,
                                             blockSignal=self.heightChanged)

    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar,
                                            blockSignal=self.widthChanged)

    def parameters(self):
        return self.params

    def export(self, fileName=None, toBytes=False, copy=False):
        if toBytes is False and copy is False and fileName is None:
            self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)")
            return
        #self.svg = QtSvg.QSvgGenerator()
        #self.svg.setFileName(fileName)
        #dpi = QtGui.QDesktopWidget().physicalDpiX()
        ### not really sure why this works, but it seems to be important:
        #self.svg.setSize(QtCore.QSize(self.params['width']*dpi/90., self.params['height']*dpi/90.))
        #self.svg.setResolution(dpi)
        ##self.svg.setViewBox()
        #targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
        #sourceRect = self.getSourceRect()

        #painter = QtGui.QPainter(self.svg)
        #try:
        #self.setExportMode(True)
        #self.render(painter, QtCore.QRectF(targetRect), sourceRect)
        #finally:
        #self.setExportMode(False)
        #painter.end()

        ## Workaround to set pen widths correctly
        #data = open(fileName).readlines()
        #for i in range(len(data)):
        #line = data[i]
        #m = re.match(r'(<g .*)stroke-width="1"(.*transform="matrix\(([^\)]+)\)".*)', line)
        #if m is not None:
        ##print "Matched group:", line
        #g = m.groups()
        #matrix = list(map(float, g[2].split(',')))
        ##print "matrix:", matrix
        #scale = max(abs(matrix[0]), abs(matrix[3]))
        #if scale == 0 or scale == 1.0:
        #continue
        #data[i] = g[0] + ' stroke-width="%0.2g" ' % (1.0/scale) + g[1] + '\n'
        ##print "old line:", line
        ##print "new line:", data[i]
        #open(fileName, 'w').write(''.join(data))

        ## Qt's SVG generator is not complete. (notably, it lacks clipping)
        ## Instead, we will use Qt to generate SVG for each item independently,
        ## then manually reconstruct the entire document.
        xml = generateSvg(self.item)

        if toBytes:
            return xml.encode('UTF-8')
        elif copy:
            md = QtCore.QMimeData()
            md.setData('image/svg+xml', QtCore.QByteArray(xml.encode('UTF-8')))
            QtGui.QApplication.clipboard().setMimeData(md)
        else:
            with open(fileName, 'w') as fh:
                fh.write(xml.encode('UTF-8'))
Ejemplo n.º 16
0
class SVGExporter(Exporter):
    Name = "Scalable Vector Graphics (SVG)"
    def __init__(self, item):
        Exporter.__init__(self, item)
        tr = self.getTargetRect()
        self.params = Parameter(name='params', type='group', children=[
            {'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)},
            {'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)},
        ])
        self.params.param('width').sigValueChanged.connect(self.widthChanged)
        self.params.param('height').sigValueChanged.connect(self.heightChanged)

    def widthChanged(self):
        sr = self.getSourceRect()
        ar = sr.height() / sr.width()
        self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged)
        
    def heightChanged(self):
        sr = self.getSourceRect()
        ar = sr.width() / sr.height()
        self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged)
        
    def parameters(self):
        return self.params
    
    def export(self, fileName=None):
        if fileName is None:
            self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)")
            return
        self.svg = QtSvg.QSvgGenerator()
        self.svg.setFileName(fileName)
        self.svg.setSize(QtCore.QSize(100,100))
        #self.svg.setResolution(600)
        #self.svg.setViewBox()
        targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height'])
        sourceRect = self.getSourceRect()
        painter = QtGui.QPainter(self.svg)
        try:
            self.setExportMode(True)
            self.render(painter, QtCore.QRectF(targetRect), sourceRect)
        finally:
            self.setExportMode(False)
        painter.end()

        ## Workaround to set pen widths correctly
        data = open(fileName).readlines()
        for i in range(len(data)):
            line = data[i]
            m = re.match(r'(<g .*)stroke-width="1"(.*transform="matrix\(([^\)]+)\)".*)', line)
            if m is not None:
                #print "Matched group:", line
                g = m.groups()
                matrix = map(float, g[2].split(','))
                #print "matrix:", matrix
                scale = max(abs(matrix[0]), abs(matrix[3]))
                if scale == 0 or scale == 1.0:
                    continue
                data[i] = g[0] + ' stroke-width="%0.2g" ' % (1.0/scale) + g[1] + '\n'
                #print "old line:", line
                #print "new line:", data[i]
        open(fileName, 'w').write(''.join(data))
Ejemplo n.º 17
0
class DeviceProfiles(SettingsPlugin):
    sigRequestRedraw = Signal()
    sigRequestReduce = Signal()
    sigSimulateCalibrant = Signal()

    name = 'Device Profiles'

    def __init__(self):
        self.headermodel = None
        self.selectionmodel = None
        self.multiAI = MultiGeometry([])
        self.AIs = dict()

        widget = ParameterTree()
        energy = SimpleParameter(name='Energy',
                                 type='float',
                                 value=10000,
                                 siPrefix=True,
                                 suffix='eV')
        wavelength = SimpleParameter(name='Wavelength',
                                     type='float',
                                     value=1.239842e-6 / 10000,
                                     siPrefix=True,
                                     suffix='m')
        self.parameter = Parameter(name="Device Profiles",
                                   type='group',
                                   children=[energy, wavelength])
        widget.setParameters(self.parameter, showTop=False)
        icon = QIcon(str(path('icons/calibrate.png')))
        super(DeviceProfiles, self).__init__(icon, "Device Profiles", widget)

        self.parameter.sigValueChanged.connect(self.sigRequestRedraw)
        self.parameter.sigValueChanged.connect(self.sigRequestReduce)
        self.parameter.sigTreeStateChanged.connect(self.simulateCalibrant)
        self.parameter.sigTreeStateChanged.connect(self.genAIs)

        self.parameter.sigValueChanged.connect(self.simulateCalibrant)

    def simulateCalibrant(self, *args):
        self.sigSimulateCalibrant.emit()

    def genAIs(self, parent, changes):
        for parameter, key, value in changes:
            if parameter.name == 'Wavelength':
                self.parameter.param('Energy').setValue(
                    1.239842e-6 / self.param('Wavelength').value(),
                    blockSignal=self.parameter.sigTreeStateChanged)
            elif parameter.name == 'Energy':
                self.parameter.param('Wavelength').setValue(
                    1.239842e-6 / self.param('Energy').value(),
                    blockSignal=self.WavelengthChanged)

        for parameter in self.parameter.children():
            if isinstance(parameter, DeviceParameter):
                device = parameter.name()
                ai = self.AI(device)
                ai.set_wavelength(self.parameter['Wavelength'])
                ai.detector = parameter['Detector']()
                ai.detector.set_binning([parameter['Binning']] * 2)
                ai.detector.set_pixel1(parameter['Pixel Size X'])
                ai.detector.set_pixel2(parameter['Pixel Size Y'])
                fit2d = ai.getFit2D()
                fit2d['centerX'] = parameter['Center X']
                fit2d['centerY'] = parameter['Center Y']
                fit2d['directDist'] = parameter['Detector Distance'] * 1000
                fit2d['tilt'] = parameter['Detector Tilt']
                fit2d['tiltPlanRotation'] = parameter['Detector Rotation']
                ai.setFit2D(**fit2d)

    def AI(self, device):
        if device not in self.AIs:
            self.addDevice(device)
        return self.AIs[device]

    def setAI(self, ai: AzimuthalIntegrator, device: str):
        self.AIs[device] = ai
        self.multiAI.ais = self.AIs.values()

        # propagate new ai to parameter
        fit2d = ai.getFit2D()
        try:
            self.setSilence(True)
            self.parameter.child(device,
                                 'Detector').setValue(type(ai.detector))
            self.parameter.child(device,
                                 'Binning').setValue(ai.detector.binning[0])
            self.parameter.child(device, 'Detector Tilt').setValue(
                fit2d['tiltPlanRotation'])
            self.parameter.child(device,
                                 'Detector Rotation').setValue(fit2d['tilt'])
            self.parameter.child(device, 'Pixel Size X').setValue(ai.pixel1)
            self.parameter.child(device, 'Pixel Size Y').setValue(ai.pixel2)
            self.parameter.child(device, 'Center X').setValue(fit2d['centerX'])
            self.parameter.child(device, 'Center Y').setValue(fit2d['centerY'])
            self.parameter.child(device, 'Detector Distance').setValue(
                fit2d['directDist'] / 1000)
            self.parameter.child('Wavelength').setValue(ai.wavelength)
        finally:
            self.setSilence(False)
        self.simulateCalibrant()

    def setSilence(self, silence):
        if silence:
            self.parameter.sigTreeStateChanged.disconnect(
                self.simulateCalibrant)
            self.parameter.sigTreeStateChanged.disconnect(self.genAIs)
        else:
            self.parameter.sigTreeStateChanged.connect(self.simulateCalibrant)
            self.parameter.sigTreeStateChanged.connect(self.genAIs)

    def addDevice(self, device):
        try:
            self.setSilence(True)
            devicechild = DeviceParameter(device)
            self.parameter.addChild(devicechild)
            ai = AzimuthalIntegrator(wavelength=self.parameter['Wavelength'])
            self.AIs[device] = ai
            self.multiAI.ais = list(self.AIs.values())
        finally:
            self.setSilence(False)

    def setModels(self, headermodel, selectionmodel):
        self.headermodel = headermodel
        self.headermodel.dataChanged.connect(self.dataChanged)
        self.selectionmodel = selectionmodel

    def dataChanged(self, start, end):
        devices = self.headermodel.item(
            self.selectionmodel.currentIndex()).header.devices()
        for device in devices:
            if device not in self.AIs:
                self.addDevice(device)

    def apply(self):
        AI = AzimuthalIntegrator(
            wavelength=self.parameter.child('Wavelength').value())
        # if Calibration.isChecked():
        #     AI.setFit2D(self.getvalue('Detector Distance') * 1000.,
        #                 self.getvalue('Center X'),
        #                 self.getvalue('Center Y'),
        #                 self.getvalue('Detector Tilt'),
        #                 360. - self.getvalue('Detector Rotation'),
        #                 self.getvalue('Pixel Size Y') * 1.e6,
        #                 self.getvalue('Pixel Size X') * 1.e6)
        # elif self.wxdiffstyle.isChecked():
        #     AI.setFit2D(self.getvalue('Detector Distance') * 1000.,
        #                 self.getvalue('Center X'),
        #                 self.getvalue('Center Y'),
        #                 self.getvalue('Detector Tilt') / 2. / np.pi * 360.,
        #                 360. - (2 * np.pi - self.getvalue('Detector Rotation')) / 2. / np.pi * 360.,
        #                 self.getvalue('Pixel Size Y') * 1.e6,
        #                 self.getvalue('Pixel Size X') * 1.e6)
        # AI.set_wavelength(self.getvalue('Wavelength'))
        # # print AI

        activeCalibration = AI

    def save(self):
        self.apply()
        return self.parameter.saveState(filter='user')

    def restore(self, state):
        pass
        # self.parameter.restoreState(state, addChildren=False, removeChildren=False)

    def wavelengthChanged(self):
        self.param('Energy').setValue(1.239842e-6 /
                                      self.param('Wavelength').value(),
                                      blockSignal=self.EnergyChanged)

    def energyChanged(self):
        self.param('Wavelength').setValue(1.239842e-6 /
                                          self.param('Energy').value(),
                                          blockSignal=self.WavelengthChanged)